Skip to content

Commit 1937ee5

Browse files
committed
experimental Mustache/PDF generation
1 parent b1af67a commit 1937ee5

7 files changed

+125
-3
lines changed

Gemfile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
source 'https://rubygems.org'
2+
gem 'pdfkit'
3+
gem 'awesome_print'
4+
gem 'redcarpet'
5+
gem 'htmlentities'
6+
gem 'mustache'

Gemfile.lock

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
awesome_print (1.6.1)
5+
htmlentities (4.3.3)
6+
mustache (0.99.4)
7+
pdfkit (0.8.2)
8+
redcarpet (2.3.0)
9+
10+
PLATFORMS
11+
ruby
12+
13+
DEPENDENCIES
14+
awesome_print
15+
htmlentities
16+
mustache
17+
pdfkit
18+
redcarpet

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@ Disclaimer: I AM NOT A LAWYER. You should run all this by your own legal counsel
1717
<span property="dct:title">Alexander D. Chaffee</span></span>
1818
has waived all copyright and related or neighboring rights to
1919
<span property="dct:title">Clauses</span>.
20-
</p>
20+
</p>
21+
22+
## Similar Projects
23+
24+
* <https://stuffandnonsense.co.uk/projects/contract-killer/>
25+
* <http://www.docracy.com/>
26+
27+

contract-style.css

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
body {
2+
font-family: Times, serif;
3+
font-size: 85%;
4+
}
5+
h1:not(:first-child) {
6+
page-break-before: always;
7+
}
8+
p {
9+
orphans: 3;
10+
widows: 3;
11+
}

contract.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
effective_date: 1/1/2000
32
consultant_name: Clark Kent
43
client_name: LexCorp, Inc., a Delaware corporation
@@ -12,7 +11,7 @@
1211
late_fee: five percent (5%)
1312
net_days: ten (10)
1413

15-
CONSULTING AGREEMENT
14+
# CONSULTING AGREEMENT
1615

1716
This CONSULTING AGREEMENT (the “Agreement”) is made as of {{effective_date}} (the “Effective Date”) by and between {{consultant_name}} (“Consultant”) and {{client_name}} (“Client”).
1817

@@ -34,6 +33,7 @@ Late payments shall be subject to a late payment fee of {{late_fee}} of the amou
3433
[Coding:]
3534
As between Consultant and Client, Consultant’s original work product prepared for Client in connection with the Services (the “Work Product”) shall be deemed a “work made for hire” under United States Copyright Law. To the extent such Work Product cannot be deemed a work made for hire, Consultant hereby assigns, sells and conveys all right, title and interest in and to such Work Product to Client in exchange for Client’s covenants hereunder.
3635
Notwithstanding the foregoing, Client understands and agrees that: (a) Ruby on Rails is an open source software (“OSS”) platform; and (b) Consultant’s Work Product shall be subject to the terms and conditions of the applicable Ruby on Rails or other OSS license.
36+
<br>
3737
[Teaching:]
3838
As between Consultant and Client, Consultant’s original work product prepared for Client in connection with the Services shall be deemed the property of Consultant, as long as such work violates neither the conditions in this Section, nor the Confidentiality provisions in Section 5.
3939

@@ -64,6 +64,7 @@ IN WITNESS WHEREOF, the Parties have executed this Agreement as of the Effective
6464

6565

6666
By: ____________________________________________
67+
6768
{{consultant_name}}
6869

6970

@@ -74,4 +75,5 @@ a {{client_location}} corporation
7475

7576

7677
By: ____________________________________________
78+
7779
{{client_signatory}}

contract.pdf

2.76 MB
Binary file not shown.

process.rb

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'rubygems'
4+
require 'bundler/setup'
5+
require 'awesome_print'
6+
7+
def usage
8+
$stderr.puts "Usage: process.rb file"
9+
exit 1
10+
end
11+
12+
source = ARGV[0] || usage
13+
14+
body = source.is_a?(IO) ? source.read : File.read(source)
15+
16+
# parse headers
17+
if body.each_line.first =~ /^\s+\w+:/
18+
headers, body = body.split("\n\n", 2)
19+
scope = Hash[headers.each_line.map do |line|
20+
line.split(':', 2).map { |x| x.strip }
21+
end]
22+
else
23+
scope = {}
24+
end
25+
ap scope
26+
27+
28+
# munge weird chars
29+
require 'htmlentities'
30+
curlies = {
31+
# todo: add more curlies
32+
# ‘ (U+2018) LEFT SINGLE QUOTATION MARK
33+
# ’ (U+2019) RIGHT SINGLE QUOTATION MARK
34+
35+
"\xe2\x80\x99" => '&apos;',
36+
"\xe2\x80\x9c" => '&#8220;',
37+
"\xe2\x80\x9d" => '&#8221;'
38+
}
39+
40+
curlies.each_pair do |nasty, pretty|
41+
body.gsub!(nasty, pretty)
42+
end
43+
44+
45+
# process mustache
46+
# https://github.com/mustache/mustache
47+
# (should mustache come before or after markdown?)
48+
require 'mustache'
49+
text = Mustache.render(body, scope)
50+
51+
52+
# convert markdown to HTML
53+
require 'redcarpet'
54+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
55+
:no_intra_emphasis => true,
56+
:tables => true,
57+
:fenced_code_blocks => true,
58+
:autolink => true,
59+
:strikethrough => true,
60+
:lax_html_blocks => false,
61+
:space_after_headers => true,
62+
:superscript => false
63+
)
64+
html = markdown.render(text)
65+
66+
67+
# generate PDF
68+
# todo: switch to Prawn?
69+
# http://asciicasts.com/episodes/220-pdfkit
70+
71+
require 'pdfkit'
72+
kit = PDFKit.new(html, :page_size => 'Letter')
73+
kit.stylesheets << "contract-style.css"
74+
file = kit.to_file("contract.pdf")
75+
76+
ap file
77+
`open #{file.path}`
78+

0 commit comments

Comments
 (0)