legal_markdown 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
- test.md
1
+ test*
2
2
  *.gem
3
3
  *.rbc
4
4
  .bundle
@@ -15,4 +15,4 @@ rdoc
15
15
  spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
- tmp
18
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ legalmd
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p429
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Introduction
2
2
 
3
- This gem will parse YAML Front Matter of Markdown Documents. Typically, this gem would be called with a md renderer, such as [Pandoc](http://johnmacfarlane.net/pandoc/), that would turn the md into a document such as a .pdf file or a .docx file. By combining this pre-processing with a markdown renderer, you can ensure that both the structured content and the structured styles necessary for your firm or organization are more strictly enforced. Plus you won't have to deal with Word any longer, and every lawyer should welcome that. Why? Because Word is awful.
3
+ This gem will parse YAML Front Matter of Markdown Documents. Typically, this gem would be called with a md renderer, such as [Pandoc](http://johnmacfarlane.net/pandoc/), that would turn the md into a document such as a .pdf file or a .docx file. By combining this pre-processing with a markdown renderer, you can ensure that both the structured content and the structured styles necessary for your firm or organization are more strictly enforced. Plus you won't have to deal with Word any longer, and every lawyer should welcome that. Why? Because Word is awful.
4
4
 
5
- Gitlaw is markdown agnostic at this point and needs to be called independently of any markdown renderer. It is easy enough to build it into your work flow by editing the way that your markdown renderer is called. For instance you can call this file just before pandoc builds it.
5
+ Gitlaw is markdown agnostic (indeed, it probably does not depend on markdown, or any of its flavors at all and *should* work with ASCII or other text based documents) at this point and needs to be called independently of any markdown renderer. It is easy enough to build it into your work flow by editing the way that your markdown renderer is called. For instance you can call this file just before pandoc builds it.
6
6
 
7
7
  ## What Does the Gem Allow For?
8
8
 
@@ -10,50 +10,91 @@ This gem was built specifically to empower the creation of structured legal docu
10
10
 
11
11
  ## How to Install This Gem?
12
12
 
13
- It is very simple. But first you must have ruby installed on your system. (Google it) Once you have ruby installed then you simply go to your terminal and type: `$> gem install legal_markdown`.
13
+ It is very simple. But first you must have ruby installed on your system. If you are on OS X then it comes standard on your machine and you do not need to do anything. If you are on Windows then the easiest way to install ruby is install 1.9.3 or higher from [rubyinstaller](http://rubyinstaller.org/). If you are on Linux, then you don't need help. Once you have ruby installed then you simply go to your terminal and type: `$> gem install legal_markdown`.
14
+
15
+ If you are looking to try out the gem, and you use [Sublime Text](http://www.sublimetext.com/) as your text editor, then you can easily install my `legal_markdown` package by visiting the repo [here](https://github.com/compleatang/Legal-Markdown-Sublime). If you install the package there is no need to install the gem, but you will still have to install ruby.
14
16
 
15
17
  ## How to Use This Gem?
16
18
 
17
- After the gem has finished its installation on your system then you can simply type `$> legalmd [filename]` where the filename is the file (in whatever flavor of markdown you use). The gem will parse the file and output the same filename. If you prefer to output as a different filename (which will allow you to keep the YAML front-matter), then you simply type `$> legalmd [input-filename] [output-filename]`.
19
+ After the gem has finished its installation on your system then you can simply type `$> legal2md [filename]` where the filename is the file (in whatever flavor of markdown you use). The gem will parse the file and output the same filename.
20
+
21
+ If you prefer to output as a different filename (which will allow you to keep the YAML front-matter), then you simply type `$> legal2md [input-filename] [output-filename]`.
22
+
23
+ If you have been working on a template or document and would like the gem to build the YAML Front-Matter (see below) automatically for you, then simply type `$> legal2md --headers [filename]`.
18
24
 
19
25
  # YAML Front-Matter
20
26
 
21
- [YAML](http://www.yaml.org/spec/1.2/spec.html) is about the easiest thing to create. At the top of your file (it MUST be at the top of the file) you simply put in three or more hyphens like so: `---` on a single line. Then on the next line you simply put in the `field` followed by a `:` (colon) followed by the `value`. For each line you put the `[field]: [value]` until you have filled everything in that you need. After you have put in all your YAML front-matter then you simply put in a single line with three more hyphens `---` to signal to the gem that it is the end of the fields. So this would look like this:
27
+ [YAML](http://www.yaml.org/spec/1.2/spec.html) is easy thing to create. At the top of your file (it MUST be at the top of the file) you simply put in three hyphens like so: `---` on a single line. Then on the next line you simply put in the `field` followed by a `:` (colon) followed by the `value`. For each line you put the `[field]: [value]` until you have filled everything in that you need. After you have put in all your YAML front-matter then you simply put in a single line with three more hyphens `---` to signal to the gem that it is the end of the fields. So this would look like this:
22
28
 
23
29
  ```
24
30
  ---
25
- title: My Perfect Contract
26
- author: Watershed Legal Services
27
- date: 2013-01-01
31
+ party1_address: "Muj Axmed Jimcaale Road, Hargeisa, Republic of Somaliland"
32
+ party1_full: "Watershed Legal Services, Ltd."
33
+ party1_reg: the Republic of Somaliland
34
+ party1_rep: "# Casey Kuhlman"
35
+ party1_short: "(\"Watershed\")"
36
+ party1_type: private company limited by shares
28
37
  ---
29
38
  ```
30
39
 
31
- ## Some Pandoc-Specific Fields
32
-
33
- There are a few fields that will be treated uniquely. The three fields in the example above (title: , author: , and date: ) will be replaced with the Pandoc fields as appropriate. Perhaps later we can (as a community) build out this functionality for other renderers but for now I've only built it to use Pandoc. If you don't use Pandoc then you can simply omit these fields and there will be no problem.
40
+ **Note**: YAML can be quite testy, so if you use any symbols or parentheses or square brackets, etc. just put the entire field inside of double quotes ("). Also, if you need double quotes within the value then you "escape" them by putting a backslash before the double quotes.
34
41
 
35
42
  # Mixins
36
43
 
37
- Mixins are straight-forward they are simple markers that can be used throughout the text to identify certain things (Court) or (Company) or (Client) to identify a few. This allows for the creation and utilization of templates that can be reused by simply updating the YAML front-matter.
44
+ Mixins are straight-forward they are simple markers that can be used throughout the text to identify certain things (Court) or (Company) or (Client) to identify a few. The example above is the YAML Front Matter for mixins. This allows for the creation and utilization of templates that can be reused by simply updating the YAML front-matter.
45
+
46
+ Mixins are structured in the form of **double curly** brackets. So, for a `{{court}}` mixin within the body of your document, the YAML front-matter would look like this:
47
+
48
+ ```
49
+ court: Regional Court of Hargeisa
50
+ ```
51
+
52
+ If you do not want a mixin turned on for a particular document just add the mixin in the YAML Frontmatter and then leave it blank. Legal_markdown will replace the mixin with an empty string so in the parsed document it will be out of your way.
53
+
54
+ ## Optional Clauses Function
55
+
56
+ When building templates for contracts, you often build in optional clauses or you build clauses that are mutually exclusive to one another. This functionality is supported by legal_markdown. Here is how to build an optional clause.
57
+
58
+ In the body of your document you put the entire clause in square-brackets (as you likely normally would) and at the beginning of the square bracket you put a mixin titled however. In the YAML Front-Matter you simply add "true" or "false" to turn that entire clause on or off. **Note**, if you do not add the mixin to your header, legal_markdown is just going to leave it as is.
59
+
60
+ You are able to nest one optional clause inside of another. However, if you do so, make sure that you include all of the sub-provisions of the master provision in the YAML matter, else legal_markdown will not be able to understand when it should close the optional provision. If you use the automatic YAML population feature either from the command line (see above) or using the Sublime package, it will simplify this process for you greatly. Another thing to note, if you include nested provisions, you can turn off an inside provision and leave an outside provision on, but if you turn off an outside provision you cannot turn on an inside provision.
38
61
 
39
- Mixins are structured in the form of **double curly** brackets (this was taken from IFTTT). So, for a `{{court}}` mixin, the YAML front-matter would look like this:
62
+ So, this is how the body of the text would look.
63
+
64
+ ```
65
+ [{{my_optional_clause}}Both parties agree that upon material breach of this agreement by either party they will both commit suicide in homage to Kurt Cobain.]
66
+ ```
67
+
68
+ Then the YAML Front Matter would look like this
40
69
 
41
70
  ```
42
- {{court}}: Regional Court of Hargeisa
71
+ my_optional_clause: true
72
+ ```
73
+
74
+ or
75
+
76
+ ```
77
+ my_optional_clause: false
43
78
  ```
44
79
 
45
- If you do not want a mixin turned on for a particular document just add the mixin in the YAML Frontmatter and then leave it blank. Legal_markdown will replace the mixin with an empty string so in the parsed document it will be out of your way.
80
+ I don't know why you would ever write such a clause, but that is why the functionality exists!
46
81
 
47
82
  # Structured Headers
48
83
 
49
- When creating many legal documents, but especially laws and contracts, we find ourselves constantly repeating structured headers. This gets utterly maddening when working collaboratively with various word processors because each word processor has its own sytles and limitations for working with ordered lists and each user of even the same word processor has different defaults. This presents a mess for those that have to clean up these lists. We waste an inordinate amount of time with "Format Painter" and other hacks that do not really allow us to focus on the text.
84
+ When creating many legal documents, but especially laws and contracts, we find ourselves constantly repeating structured headers. This gets utterly maddening when working collaboratively with various word processors because each word processor has its own styles and limitations for working with ordered lists and each user of even the same word processor has different defaults. This presents a mess for those that have to clean up these lists. We waste an inordinate amount of time with "Format Painter" and other hacks that do not really allow us to focus on the text.
50
85
 
51
- In order to address this problem, I have built functionality into legal_markdown that gets around this. Here is how structured headers work in the gem. At the beginning of the line you simply type the level in which the provision resides by the number of lowercase "l" followed by a period and then a space. So a top level provision (perhaps a Chapter, or Article depending on your document) will begin with `l. The provision ...` A second level provision (a Section or whatnot) will begin with `ll. Both parties agree ...` A third level provision will begin with `lll. Yaddy Yadda ...` And so on. These will reside in the body of the text.
86
+ In order to address this problem, I have built functionality into legal_markdown that gets around this. Here is how structured headers work in the gem.
52
87
 
53
- Then you can describe the functionality that you require in the YAML front-matter. In the YAML front-matter you will simply add the following fields: `level-1` and then the `: ` followed by what the format you would like it to be in. Currently there are a few possible options at this time (for those using pandoc at least):
88
+ Wherever you wish to start the block of structured headers just put in ````` Three backticks (~ without the shift) at the beginning of the line. Then start the block of structured headers on the next line. When you are done with the block just put the same three backticks at the beginning of the line and continue your document.
54
89
 
55
- 1. `level-1: 1.` will format that level of the list as 1. 2. 3. etc.; This is the default functionality;
56
- 2. `level-1: (1)` will provide for the same numbering only within parenteticals rather than followed by a period;
90
+ At the beginning of the line you simply type the level in which the provision resides by the number of lowercase "l" followed by a period and then a space. So a top level provision (perhaps a Chapter, or Article depending on your document) will begin with `l. The provision ...` A second level provision (a Section or whatnot) will begin with `ll. Both parties agree ...` A third level provision will begin with `lll. Yaddy Yadda ...` And so on. These will reside in the body of the text.
91
+
92
+ When the gem parses the document it will automatically add and reset each level in the tree that you set up based on the criteria you establish.
93
+
94
+ Then you can describe the functionality that you require in the YAML front-matter. In the YAML front-matter you will simply add the following fields: `level-1` and then the `: ` followed by what the format you would like it to be in. Currently there are a few possible options at this time:
95
+
96
+ 1. `level-1: 1.` will format that level of the list as 1. 2. 3. etc.; This is the default functionality;
97
+ 2. `level-1: (1)` will provide for the same numbering only within parenteticals rather than followed by a period;
57
98
  3. `level-1: A.` will format with capital letters followed by a period (e.g, A., B., C., etc.);
58
99
  4. `level-1: (A)` will format the same as the above only with the capital letters in a parentetical;
59
100
  5. `level-1: a.` will format with lowercase letters followed by a period;
@@ -63,58 +104,46 @@ Then you can describe the functionality that you require in the YAML front-matte
63
104
  9. `level-1: i.` will format with lowercase Roman numerals followed by a period;
64
105
  10. `level-1: (i)` will format with lowercase Roman numerals within a parententical..
65
106
 
66
- Obviously you will replace `level-1` with `level-2`, etc. Although this functionality was built into the gem, it is generally not the best practice. A better practice is to let the gem make the replacements and reformat the markdown and then use your rendering system and its default reference documents to set the styles you need.
107
+ Obviously you will replace `level-1` with `level-2`, etc.
67
108
 
68
- ## No Reset Function
69
-
70
- Sometimes in legal documents (particularly in laws) you want to build multiple structured header levels, but you do not want to reset all of the headers when going up the tree. For example, in some laws you will have Chapters, Parts, Sections, ... and you will want to track Chapters, Parts and Sections but when you go up to Parts you will not want to reset the Sections to one.
71
-
72
- This functionality is built in with a `no-reset` function. You simply add a `no-reset` field to your YAML header and note the headers that you do not want to reset by their l., ll. notation. Separate those levels you do not want reset with commas. Example YAML line:
109
+ In addition to the reference portion of the structured header, you can add in whatever text you wish. For example, if you want the top level to be articles with a number and then a period, the next level down to be sections with a number in parentheses, and the next level down to be a letter in parentheses then this is what the YAML front matter would look like.
73
110
 
74
111
  ```
75
- no-reset: l., ll., lll.
112
+ ---
113
+ level-1: Article 1.
114
+ level-2: Section (1)
115
+ level-3: (a)
116
+ ---
76
117
  ```
77
118
 
78
- This will not reset level-1, level-2, or level-3 when it is parsing the document and those levels will be numbered sequentially through the entire block rather than reseting when going to a higher block, levels not in this reset, e.g., llll. and lllll. will be reset when going up a level in the tree. Obviously the level 1 headers will never reset.
79
-
80
- ## No Indent Function
119
+ As of version 0.2.0, you can start on any number or letter you wish. So if you want the first Article to be Article 100. instead of Article 1. there is no problem with that. One thing to be careful of if you do not start with the default numbering/lettering is that you should likely turn off the reset function for that level (see below) or else when the gem is parsing the document it will reset the level based on the default numbering/lettering rather than the initial numbering/lettering you established. Also, be careful if you want to start with letters that also match with Roman Numerals (I, V, X, L, C, D, M) whether upper or lower case as the gem parses Roman's first and if you want a sequence similar to (a), (b) but you put in (c) the gem will default to the lowercase version of the Roman Numeral C (100).
81
120
 
82
- Sometimes you will not want to use Pandoc's listing function. Basically if you are outputting to .pdf, .odt, .doc(x) you may want to keep tight to the margins. This functionality is built into legal_markdown with a `no-indent` function. You simply add a `no-ident` field to your YAML header and not the headers you do not want to indent by their l., ll. notation. Separate those levels you do not want to reset with commas as with the `no-reset` function. Any levels *below* the last level in the `no-indent` function will be indented four spaces.
83
-
84
- ## Optional Clauses Function
85
-
86
- When building templates for contracts, you often build in optional clauses or you build clauses that are mutually exclusive to one another. This functionality is supported by legal_markdown. This is how you build an optional clause. In the body of your text you put the entire clause in square-brackets (as you likely normally would) and at the beginning of the square bracket you put a mixin titled however. In the YAML Front-Matter you simply add true or false to turn that entire clause on or off. **Note**, if you do not add the mixin to your header, legal_markdown is just going to leave it as is.
121
+ ## No Reset Function
87
122
 
88
- You are able to nest one optional clause inside of another. However, if you do so, make sure that you include all of the sub-provisions of the master provision in the YAML matter, else legal_markdown will not be able to understand when it should close the optional provision. Another thing to note, if you include nested provisions, you can turn off an inside provision and leave an outside provision on, but if you turn off an outside provision you cannot turn on an inside provision.
123
+ Sometimes in legal documents (particularly in laws) you want to build multiple structured header levels, but you do not want to reset all of the headers when going up the tree. For example, in some laws you will have Chapters, Parts, Sections, ... and you will want to track Chapters, Parts and Sections but when you go up to Parts you will not want to reset the Sections to one.
89
124
 
90
- So, this is how the body of the text would look.
125
+ This functionality is built in with a `no-reset` function. You simply add a `no-reset` field to your YAML header and note the headers that you do not want to reset by their l., ll. notation. Separate those levels you do not want reset with commas. Example YAML line:
91
126
 
92
127
  ```
93
- [{{my_optional_clause}}Both parties agree that upon material breach of this agreement by either party they will both commit suicide in homage to Kurt Cobain.]
128
+ no-reset: l., ll., lll.
94
129
  ```
95
130
 
96
- Then the YAML Front Matter would look like this
97
-
98
- ```
99
- my_optional_clause: true
100
- ```
131
+ This will not reset level-1, level-2, or level-3 when it is parsing the document and those levels will be numbered sequentially through the entire block rather than reseting when going to a higher block, levels not in this reset, e.g., llll. and lllll. will be reset when going up a level in the tree. Obviously the level 1 headers will never reset.
101
132
 
102
- or
133
+ ## No Indent Function
103
134
 
104
- ```
105
- my_optional_clause: false
106
- ```
135
+ If you are outputting to .pdf, .odt, .doc(x) you may want to keep some of the header levels tight to the margins. This functionality is built into legal_markdown with a `no-indent` function. You simply add a `no-indent` field to your YAML header and not the headers you do not want to indent by their l., ll. notation. Separate those levels you do not want to reset with commas as with the `no-reset` function. Any levels *below* the last level in the `no-indent` function will be indented four spaces for each level.
107
136
 
108
- I don't know why you would ever write such a clause, but that is why the functionality exists!
137
+ ## Examples
109
138
 
110
- ## Example
139
+ The syntax should be straight-forward. If you learn by seeing rather than by reading, take a look at the Watershed lmd [repos](https://github.com/watershedlegal/commercial-documents) where we keep our contract templates for more examples. That link is for some commercial documents, but we have more on the Watershed Github page.
111
140
 
112
141
  If you use a system like Pandoc you can establish a system wherein the styles that you establish in the reference.docx or reference.odt or the latex style references can make up for the lack of granular fuctionality. When you build your reference.odt for example and you want to have a contract look like this:
113
142
 
114
143
  ```
115
144
  Article 1. Provision for Article 1.
116
145
 
117
- Section 1.1. Provision for Section 1.1.
146
+ Section 1.1. Provision for Section 1.1.
118
147
 
119
148
  1.1.1 Provision for 1.1.1.
120
149
 
@@ -147,9 +176,6 @@ lll. Provision for 1.2.2.
147
176
 
148
177
  ```
149
178
  ---
150
- title: Wonderful Contract
151
- author: Your Name
152
- date: today
153
179
  level-1: 1.
154
180
  level-2: A.
155
181
  level-3: a.
@@ -158,61 +184,135 @@ level-3: a.
158
184
 
159
185
  ### Step 3: Modify your reference.odt or reference.docx
160
186
 
161
- In Libreoffice you would modify your template reference.odt as you need it. You would go to Format -> Bullets and Numbering -> Options.
187
+ In Libreoffice you would modify your template reference.odt as you need it. You would go to Format -> Bullets and Numbering -> Options.
162
188
 
163
189
  1. First you would select Level 1 (on the left). In the Before field you would add "Article " (without the quotes, but not the space). In the After field you would add a period. In the Numbering field you would select 1, 2, 3, .... And in the Show sublevels field you would choose 1
164
190
  2. Second you would select Level 2 (on the left). In the Before field you would add "Section " (without the quotes, but with the space). In the After field you would add a period. In the Numbering field you would select 1, 2, 3, .... And in the Show sublevels field you would choose 2.
165
191
  3. Third you would select Level 3 (on the left). In the Before field you would add nothing (to accomplish the above desired output). In the After field you would add a period. in the Show sublevels field you would choose 3.
166
- 4. Lastly you would make sure that Consecutive Numbering (field at the bottom) was turned off.
167
- 5. You can make sure that all the indenting is as desired in the Position Tab.
192
+ 4. Lastly you would make sure that Consecutive Numbering (field at the bottom) was turned off.
193
+ 5. You can make sure that all the indenting is as desired in the Position Tab.
168
194
 
169
- Then you would save the reference.odt as a new name perhaps contract-reference.odt in your Pandoc reference folder.
195
+ Then you would save the reference.odt as a new name perhaps contract-reference.odt in your Pandoc reference folder.
170
196
 
171
197
  ### Step 3(a): Add Precursors to Headers
172
198
 
173
- *Note*: I only use these when I'm using pandoc to move directly to html or pdf files (a fuller suite of this is what we're working towards at Watershed, along with the fantastic team at [FrontlineSMS](http://www.frontlinesms.com/about-us/) and others hopefully). If you want to use `legal_markdown` along with .odt or .docx files probably better to utilize the workflow described *supra*.
174
-
175
- Now that you've been warned, here's how you use precursors. Within the text of the document nothing changes. In the YAML front matter you will leave it as it was before. All you need to do is add any word or other marker before the trigger. What `legal_markdown` will do is to look at the last two characters if the marker ends in a period or three if it ends in a paren, and then everything else it will place into a precursor. If you want to reference the preceding level (like 1.1.1 in the example above) then simply put in {pre}. I'll try to make this less fragile down the road, but for now it is what it is. So, your YAML front matter will look like this:
199
+ Within the text of the document nothing changes. In the YAML front matter you will leave it as it was before. All you need to do is add any word or other marker before the trigger. If you want to reference the preceding level (like 1.1.1 in the example above) then simply put in `pre`.So, your YAML front matter will look like this:
176
200
 
177
201
  ```
178
202
  ---
179
- title: Wonderful Contract
180
- author: Your Name
181
- date: today
182
203
  level-1: Article 1.
183
- level-2: pre 1.
184
- level-3: pre a.
204
+ level-2: Section pre 1.
205
+ level-3: pre 1.
206
+ ---
207
+ ```
208
+
209
+ This is how I build most of my contracts.
210
+
211
+ ### Step 3(b) Add Another Type of Precursors to Headers
212
+
213
+ Sometimes, particularly in laws, the structure is something akin to Chapter 1 and then Section 101, Section 102, ... Chapter 9, Section 901, Section 902, etc. As of version 0.2.0 you can easily adopt this structure to your document by using the `preval` feature within the YAML front matter. If you combined this structure by also using markdown headers the YAML front matter would look something like this:
214
+
215
+ ```
185
216
  ---
217
+ level-1: "# Chapter 1."
218
+ level-2: "## Section preval 1."
219
+ level-3: pre(a)
220
+ no-indent: l., ll.
221
+ ---
222
+ ```
223
+
224
+ This would output (using the same text from the body of the document typed in step 1) as:
225
+
186
226
  ```
227
+ # Chapter 1. Provision for Article 1.
228
+
229
+ ## Section 101. Provision for Section 1.1.
230
+
231
+ 101(a) Provision for 1.1.1.
232
+
233
+ 101(b) Provision for 1.1.2.
187
234
 
188
- The other thing you need to be aware of if you use this method is that when `legal_markdown` parses the input markdown it have to hardcode in the numbering. This means that you'll lose any features of automatic lists and list nesting which your markdown renderer may give you if you simply placed the triggers without any precursors.
235
+ ## Section 102. Provision for Section 1.2.
189
236
 
190
- ### Step 4: Run Legal-Markdown and Pandoc
237
+ 102(a) Provision for 1.2.1.
191
238
 
192
- Make sure when you run Pandoc you use the new reference document that you created as the basis.
239
+ 103(b) Provision for 1.2.2.
240
+
241
+ ...
242
+ ```
243
+
244
+ ### Step 4: Run Legal-Markdown and Pandoc (or other markdown processor)
245
+
246
+ Make sure when you run Pandoc you use the new reference document that you created as the basis.
193
247
 
194
248
  I do not use latex to create pdfs nor do I use Word, but the functionality will be similar with Word, and if you're using latex then you can figure out how to mirror this workflow.
195
249
 
250
+ ## A Few Other Features
251
+
252
+ I find, particularly when I'm working with contracts and templates that I needed a few more features.
253
+
254
+ ### Working with Cross Reference Provisions.
255
+
256
+ One thing I needed was the ability to cross reference between provisions where the text of Section 16 refers back to Section 12. When you're working with templates you may turn on or off provisions after reviewing a draft with a client. Also when you're working in a `lmd` file you do not see what the Section reference is within the document (that's the whole point). So, as of 0.2.0, there is a cross referencing feature to `legal_markdown`.
257
+
258
+ In order to try to make the gem interoperable with as many finishing renders as possible I've tried to keep the switches and symbols unique to the gem to a very few (so far within the body of the document we've only relied on square brackets and double curly braces to do all of the work). But there is only so much one can do with those symbols. So I have had to add one more symbol to get the cross-referencing right and unambiguous to the parser. Within your structured headers block simply place a reference (which you can make up and remember, it can contain letters, numbers, or symbols) within pipes "|" (the key above the enter key on US keyboards). First stake the piped reference to the provision which you want to reference to. Then other provisions can refer to it (either before or after the reference point within the document).
259
+
260
+ For example, if the YAML front matter looked like this:
261
+
262
+ ```
263
+ ---
264
+ level-1: "# Article 1."
265
+ level-2: "Section 1."
266
+ level-3: (a)
267
+ no-indent: l., ll.
268
+ ---
269
+ ```
270
+
271
+ and the body of the text looked like this:
272
+
273
+ ```
274
+ ...
275
+ ll. |123| This provision will need to be referenced later.
276
+ ll. Provision
277
+ lll. As stated in |123|, whatever you need to say.
278
+ ...
279
+ ```
280
+
281
+ would output to this:
282
+
283
+ ```
284
+ Section 7. This provision will need to be referenced later.
285
+
286
+ Section 8. Provision
287
+
288
+ (a) As stated in Section 7, whatever you need to say.
289
+ ```
290
+
291
+ #### Working with Partials
292
+
293
+ In particular when I work with templates, I was realizing that it would be nice to be a bit more DRY (don't repeat yourself) in my contract building. In order to help with this, I wanted to build a partials feature. Probably not a lot of people will use this, but here is how you do it. Let's say you put your standard interpretation, notice, severance, boilerplate typically at the end of the contract just before the signature block. Let's also assume that you have multiple contract templates and they all mostly use the same boilerplate final provisions.
294
+
295
+ If you were lawyering like coders think then you would abstract these provisions into their own file within your contracts templates folder. Then you would change all of your templates to reference back to that partial. Later, if there is some change in the law you just go into the partial, make the necessary change to adopt to the change in law or interpretation, and then all of your templates which refer to that partial are automatically updated. A bit more simple then updating each and every one of your templates, eh?
296
+
297
+ Partials are simple. They use the `@import [filename]` syntax. So if your final provisions are kept in a file in the same folder called final_provisions.lmd you would put `@import final_provisions.lmd` on its own line (either within a structured headers block or outside of it) and the gem will import the contents of the partial before chewing on the whole contract. If your partial was located in another directory you just type that in just like you would on the command line `@import ~/gitlaw/contracts/commercial/partials/final_provisions.lmd` or wherever your partial is.
298
+
196
299
  ## A Few Gotchas
197
300
 
198
- * When you are using structured headers of legal_markdown you should make the lists tight. Do not add blank lines in between the list levels or the gem will think you are creating a new list. If you are trying to create a new list then by all means go ahead as the blank lines will break the parsing. On the roadmap is functionality for multiple blocks, but at this point in the Gem's development it will only run one block through the modification methods.
199
- * If you use the reference.odt or reference.docx to override the default formating of the list then it is not optimal add level-1 or level-2 leading text or utilize the different marker functionality (e.g., (i) or (a) and the like) to the YAML front-matter. The optimal way is to use the defaults that pandoc has or whatever renderer you use along with legal_markdown to set the spacing and then use the reference styles to build the functionality that you would like from the word processor side. The leading text and different marker systems are predominately built for html output.
200
301
  * Legal_markdown is optimized primarily for contracts, legislation, and regulations. It is not optimized for cases. For memoranda and filings I use the mixin portion but not the header portion which is enough to meet my needs - in particular, when matched with Sublime Text snippets. If you area looking for a more complete solution for cases and filings I would recommend the [Precedent Gem](https://github.com/BlackacreLabs/precedent) built by [Kyle Mitchell](https://github.com/kemitchell) for [Blackacre Labs](https://github.com/BlackacreLabs)
302
+ * At this point, you cannot have more than 9 levels for headers, but if you have more than 9 levels of headers you have some insane case study which will require more than this tool to cope with.
303
+
304
+ ## Roadmap / TODO
305
+
306
+ - [X] Allow for lll. or l3. leaders based on leader-style: l. or leader-style: l1. switch in YAML.
307
+ - [X] Implement partials as `@include filename`.
308
+ - [X] Implement internal cross references as `ll. |123| Provision`
309
+ - [X] Different starting values.
310
+ - [X] Pre-VALUE functionality where Article 1 subs to 101.
311
+ - [X] Handle exceptions better as it is very brittle right now.
312
+ - [X] YAML Maker.
313
+ - [ ] md2lmd functionality. At this point legal_markdown cannot take a markdown document and parse it to build a structured legal document. Legal_markdown only works with a renderer to *create* documents but not to *parse* legal documents to create markdown.
201
314
 
202
- # Roadmap / TODO
203
-
204
- - [X] Make a no-reset option for certain levels that should not reset when moving up the tree.
205
- - [X] Make no indent option.
206
- - [X] Optional clauses in brackets with a mixin inside. Turn the mixin to false and the whole clause will not be rendered. For a mixin that simply turns on or off, must make a function whereby the mixin is true that it is turned on.
207
- - [ ] Handle Exceptions better as it is very brittle right now.
208
- - [ ] Different input and output files.
209
- - [ ] Implement partials.
210
- - [ ] Leave the YAML Front Matter
211
- - [ ] Definitions. For now these can be used as mixins but that functionality needs to improve.
212
- - [ ] Date = today function.
213
- - [ ] Handle against multiple blocks in a document as this currently will not work.
214
- - [ ] ??? Should this switch to TOML rather than YAML frontmatter...?
215
- - [ ] legal2md functionality. At this point legal_markdown cannot take a markdown document and parse it to build a structured legal document. Legal_markdown only works with a renderer to *create* documents but not to *parse* legal documents to create markdown.
315
+ If you have needs that you think other people may have, feel free to put them up in the Github issues.
216
316
 
217
317
  # Contributing
218
318
 
@@ -227,6 +327,6 @@ I do not use latex to create pdfs nor do I use Word, but the functionality will
227
327
 
228
328
  MIT License - (c) 2013 - Watershed Legal Services, PLLC. All copyrights are owned by [Watershed Legal Services, PLLC](http://watershedlegal.com). See License file.
229
329
 
230
- This software is provided as is and specifically disclaims any implied warranties of fitness for any purpose whatsoever. By using this software you agree to hold harmless Watershed Legal Services and its Members for any perceived harm that using this software may have caused you.
330
+ This software is provided as is and specifically disclaims any implied warranties of fitness for any purpose whatsoever. By using this software you agree to hold harmless Watershed Legal Services and its Members for any perceived harm that using this software may have caused you.
231
331
 
232
- In other words, don't be a jerk.
332
+ In other words, don't be a jerk.
data/bin/legal2md ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # == USAGE
4
+ # legal2md input_file output_file
5
+
6
+ require 'legal_markdown'
7
+ LegalToMarkdown.main(ARGV)
@@ -18,9 +18,9 @@ Gem::Specification.new do |s|
18
18
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency "roman-numerals"
21
+ # s.add_dependency
22
22
 
23
23
  s.description = <<desc
24
- This gem will parse YAML Front Matter of Markdown Documents. Typically, this gem would be called with a md renderer, such as Pandoc, that would turn the md into a document such as a .pdf file or a .docx file. By combining this pre-processing with a markdown renderer, you can ensure that both the structured content and the structured styles necessary for your firm or organization are more strictly enforced. Plus you won't have to deal with Word any longer, and every lawyer should welcome that. Why? Because Word is awful.
24
+ This gem will parse YAML Front Matter of Markdown Documents. Typically, this gem would be called with a md renderer, such as Pandoc, that would turn the md into a document such as a .pdf file or a .docx file. By combining this pre-processing with a markdown renderer, you can ensure that both the structured content and the structured styles necessary for your firm or organization are more strictly enforced. Plus you won't have to deal with Word any longer, and every lawyer should welcome that. Why? Because Word is awful.
25
25
  desc
26
26
  end
@@ -0,0 +1,115 @@
1
+ #! ruby
2
+ require 'yaml'
3
+
4
+ class MakeYamlFrontMatter
5
+
6
+ def initialize(*args)
7
+ data = load(*args)
8
+ parsed_file = find_yaml_if_yaml(data)
9
+ new_yaml_as_array = scan_and_filter_yaml(parsed_file[0], parsed_file[1])
10
+ new_yaml = build_new_yaml_frontmatter(new_yaml_as_array)
11
+ write_it( new_yaml + parsed_file[1] )
12
+ end
13
+
14
+ def load(*args)
15
+ begin
16
+ @file = ARGV[-1]
17
+ if @file != "-"
18
+ source_file = File::read(@file) if File::exists?(@file) && File::readable?(@file)
19
+ else
20
+ source_file = STDIN.read
21
+ end
22
+ source_file.scan(/(@include (.+)$)/).each do |set|
23
+ partial_file = set[1]
24
+ to_replace = set[0]
25
+ partial_contents = File::read(partial_file) if File::exists?(partial_file) && File::readable?(partial_file)
26
+ source_file.gsub!(to_replace, "[PARTIALSTART]\n" + partial_contents + "\n[PARTIALENDS][#{to_replace}]")
27
+ end
28
+ return source_file
29
+ rescue => e
30
+ puts "Sorry, I could not read the input file #{@file}: #{e.message}."
31
+ exit 0
32
+ end
33
+ end
34
+
35
+ def find_yaml_if_yaml( source )
36
+ begin
37
+ yaml_pattern = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
38
+ parts = source.partition( yaml_pattern )
39
+ if parts[1] != ""
40
+ headers = YAML.load(parts[1])
41
+ content = parts[2]
42
+ else
43
+ headers = {}
44
+ content = source
45
+ end
46
+ rescue => e
47
+ puts "Sorry, something went wrong when I was loading the YAML front matter: #{e.message}."
48
+ end
49
+ return [headers, content]
50
+ end
51
+
52
+ def scan_doc(content, pattern)
53
+ headers = content.scan(pattern).uniq.sort.flatten
54
+ if pattern == @structured_headers_pattern
55
+ headers = convert_ll_to_level_two(headers)
56
+ end
57
+ return headers
58
+ end
59
+
60
+ def convert_ll_to_level_two(levels)
61
+ # receives an array in form ["l.", "ll.", "lll."] returns array in form ["level-1", "level-2"]
62
+ levels.inject([]){|arr, level| level[/(l+)./]; arr << "level-" + $1.length.to_s}
63
+ end
64
+
65
+ def filter_yaml(yaml_data, stuff)
66
+ # yaml_data will be a hash, stuff is an array, returns a filtered hash
67
+ stuff_in_yaml = stuff.inject({}) do |hash, elem|
68
+ yaml_data.has_key?(elem) ? hash.merge({elem => yaml_data[elem]}) : hash.merge({elem => ""})
69
+ end
70
+ end
71
+
72
+ def scan_and_filter_yaml(yaml_data, content)
73
+ mixin_pattern = /[^\[]{{(\S+)}}/
74
+ opt_clauses_pattern = /\[{{(\S+)}}/
75
+ @structured_headers_pattern = /(^l+.)/
76
+ mixins = filter_yaml(yaml_data, scan_doc(content, mixin_pattern))
77
+ opt_clauses = filter_yaml(yaml_data, scan_doc(content, opt_clauses_pattern))
78
+ levels = filter_yaml(yaml_data, scan_doc(content, @structured_headers_pattern))
79
+ extras = filter_yaml(yaml_data, %w{no-indent no-reset leader-style})
80
+ return [mixins, opt_clauses, levels, extras]
81
+ end
82
+
83
+ def build_new_yaml_frontmatter(yaml_data_as_array)
84
+ front = "---\n\n"
85
+ if yaml_data_as_array[0]
86
+ front << "\# Mixins\n"
87
+ yaml_data_as_array[0].each{ |head, val| front << head + ": " + val.to_s + "\n" }
88
+ end
89
+ if yaml_data_as_array[1]
90
+ front << "\n\# Optional Clauses\n"
91
+ yaml_data_as_array[1].each{ |head, val| front << head + ": " + val.to_s + "\n" }
92
+ end
93
+ if yaml_data_as_array[2]
94
+ front << "\n\# Structured Headers\n"
95
+ yaml_data_as_array[2].each{ |head, val| front << head + ": \"" + val.to_s + "\"\n" }
96
+ end
97
+ if yaml_data_as_array[3]
98
+ yaml_data_as_array[3].each{ |head, val| front << head + ": " + val.to_s + "\n" }
99
+ end
100
+ front << "\n---\n\n"
101
+ end
102
+
103
+ def write_it( final_content )
104
+ final_content.scan(/(\[PARTIALSTART\].*?\[PARTIALENDS\]\[(.*?)\])/m).each do |set|
105
+ replacer = set[1]
106
+ to_replace = set[0]
107
+ final_content.gsub!(to_replace, replacer)
108
+ end
109
+ if @file != "-"
110
+ File.open(@file, "w") {|f| f.write( final_content ) }
111
+ else
112
+ STDOUT.write final_content
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,77 @@
1
+ # Extracted from Roman Numerals gem
2
+
3
+ # Copyright (c) 2011 Andrew Vos
4
+
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+
25
+ module RomanNumerals
26
+ @base_digits = {
27
+ 1 => 'I',
28
+ 4 => 'IV',
29
+ 5 => 'V',
30
+ 9 => 'IX',
31
+ 10 => 'X',
32
+ 40 => 'XL',
33
+ 50 => 'L',
34
+ 90 => 'XC',
35
+ 100 => 'C',
36
+ 400 => 'CD',
37
+ 500 => 'D',
38
+ 900 => 'CM',
39
+ 1000 => 'M'
40
+ }
41
+
42
+ def self.to_roman_upper(value)
43
+ value = value.to_i
44
+ result = ''
45
+ @base_digits.keys.reverse.each do |decimal|
46
+ while value >= decimal
47
+ value -= decimal
48
+ result += @base_digits[decimal]
49
+ end
50
+ end
51
+ result
52
+ end
53
+
54
+ def self.to_roman_lower(value)
55
+ value = value.to_i
56
+ result = ''
57
+ @base_digits.keys.reverse.each do |decimal|
58
+ while value >= decimal
59
+ value -= decimal
60
+ result += @base_digits[decimal]
61
+ end
62
+ end
63
+ result.downcase
64
+ end
65
+
66
+ def self.to_decimal_string(value)
67
+ value.upcase!
68
+ result = 0
69
+ @base_digits.values.reverse.each do |roman|
70
+ while value.start_with? roman
71
+ value = value.slice(roman.length, value.length)
72
+ result += @base_digits.key roman
73
+ end
74
+ end
75
+ result.to_s
76
+ end
77
+ end