law_doc 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.org +82 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/law_doc.gemspec +34 -0
- data/lib/blankable_date.rb +239 -0
- data/lib/law_doc/address.rb +49 -0
- data/lib/law_doc/case.rb +318 -0
- data/lib/law_doc/core_ext/array.rb +51 -0
- data/lib/law_doc/core_ext/nil.rb +9 -0
- data/lib/law_doc/core_ext/numeric.rb +34 -0
- data/lib/law_doc/core_ext/string.rb +3 -0
- data/lib/law_doc/core_ext.rb +4 -0
- data/lib/law_doc/court.rb +48 -0
- data/lib/law_doc/document.rb +452 -0
- data/lib/law_doc/error.rb +2 -0
- data/lib/law_doc/init_types.rb +182 -0
- data/lib/law_doc/judge.rb +28 -0
- data/lib/law_doc/lawyer.rb +111 -0
- data/lib/law_doc/party.rb +40 -0
- data/lib/law_doc/person.rb +291 -0
- data/lib/law_doc/phone.rb +62 -0
- data/lib/law_doc/version.rb +3 -0
- data/lib/law_doc.rb +73 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dfdd33df5942fb08182facdb203f53b222844f0f3be50132ede38383a155fade
|
4
|
+
data.tar.gz: cf991c3177a676c3c91a533eb6ef4318054533c048cc43c659e6789457443fef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4bfd6a7b2bbfa183cb37ca7bb82f0a06a2c39b4bbc5db5bcfc521fbdb5cf16980e43ec8878f5176bb112158caf47e01ac574c5551d4c8732696f301760aaec17
|
7
|
+
data.tar.gz: 67c7cfa6dbe9857806c84f47fdb8dd0b634c887157ed08c961602bf9683485361cff0a2a9d4e64fc31ca489c582a72fe8885cdacc3308008d8122ba6c961e313
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.org
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
* LawDoc
|
2
|
+
|
3
|
+
The ~law_doc~ gem provides classes meant to provide the glue between the ~ydl~
|
4
|
+
data language and the ~lawdoc.cls~ LaTeX document class and the ~legal~ style
|
5
|
+
files for composing legal documents. Getting ruby code executed as part of LaTeX
|
6
|
+
pre-processing is the job of ~erbtex~, itself a ruby command-line that executes
|
7
|
+
ruby code embedded in the LaTeX file between delimiters ~{:~ and ~:}~ before
|
8
|
+
handing the resulting text off to LaTeX. The ~law_doc~ gem provides objects for
|
9
|
+
such things as Person, Lawyer, Party, Court, Case, and Document, as well as
|
10
|
+
other lower-level supporting classes such as Email and Phone. These classes know
|
11
|
+
how to spit out LaTeX macros suitable for use in a ~lawdoc.cls~ document class.
|
12
|
+
The classes can be constructed from the ~YAML~-like ~ydl~ files found in the
|
13
|
+
file system simply
|
14
|
+
|
15
|
+
All that is needed is a LaTeX document such as the following
|
16
|
+
#+BEGIN_EXAMPLE
|
17
|
+
\documentclass{lawdoc}
|
18
|
+
|
19
|
+
{:=
|
20
|
+
require 'law_doc'
|
21
|
+
LawDoc.document do
|
22
|
+
title 'Brief in Support of Plaintiff\'s Motion for Summary Judgment'
|
23
|
+
kase Ydl[:cases][:erickson]
|
24
|
+
on_behalf_of 'plaintiffs'
|
25
|
+
signers Ydl[:lawyers][:ded], Ydl[:lawyers][:cjh]
|
26
|
+
sig_date '2015-11-20'
|
27
|
+
server signer
|
28
|
+
service_date sig_date
|
29
|
+
end
|
30
|
+
:}
|
31
|
+
|
32
|
+
\begin{document}
|
33
|
+
\makecaption
|
34
|
+
|
35
|
+
\makefullsignature
|
36
|
+
|
37
|
+
\newpage
|
38
|
+
\makecertificateofservice
|
39
|
+
\end{document}
|
40
|
+
#+END_EXAMPLE
|
41
|
+
|
42
|
+
to activate macros such as ~\makecaption~ that perform the tiresome parts of a
|
43
|
+
legal document.
|
44
|
+
|
45
|
+
The call to ~LawDoc.document~ defines the current document by reference to a
|
46
|
+
Hash called ~Ydl~ of items defined in the ~.ydl~ files found in the file system.
|
47
|
+
|
48
|
+
** Installation
|
49
|
+
|
50
|
+
Add this line to your application's Gemfile:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
gem 'law_doc'
|
54
|
+
```
|
55
|
+
|
56
|
+
And then execute:
|
57
|
+
|
58
|
+
$ bundle
|
59
|
+
|
60
|
+
Or install it yourself as:
|
61
|
+
|
62
|
+
$ gem install law_doc
|
63
|
+
|
64
|
+
** Usage
|
65
|
+
|
66
|
+
TODO: Write usage instructions here
|
67
|
+
|
68
|
+
** Development
|
69
|
+
|
70
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
71
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
72
|
+
prompt that will allow you to experiment.
|
73
|
+
|
74
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
75
|
+
release a new version, update the version number in `version.rb`, and then run
|
76
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
77
|
+
git commits and tags, and push the `.gem` file to
|
78
|
+
[rubygems.org](https://rubygems.org).
|
79
|
+
|
80
|
+
** Contributing
|
81
|
+
|
82
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ddoherty03/law_doc.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/law_doc.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'law_doc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'law_doc'
|
8
|
+
spec.version = LawDoc::VERSION
|
9
|
+
spec.authors = ['Daniel E. Doherty']
|
10
|
+
spec.email = ['ded@ddoherty.net']
|
11
|
+
spec.summary = %q{Ruby classes to assist in writing LaTeX legal documents.}
|
12
|
+
spec.description = <<~DESC
|
13
|
+
|
14
|
+
A set of classes for legal document elements such as Document, Case, Lawyer, Party, Court, Judge, etc. Made to play
|
15
|
+
well with the ydl and erbtex gems.
|
16
|
+
|
17
|
+
DESC
|
18
|
+
|
19
|
+
spec.homepage = 'https://github.com/ddoherty03/law_doc'
|
20
|
+
|
21
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
22
|
+
f.match(%r{^(test|spec|features)/})
|
23
|
+
end
|
24
|
+
spec.require_paths = ['lib']
|
25
|
+
|
26
|
+
spec.add_dependency 'fat_core'
|
27
|
+
spec.add_dependency 'activesupport', '~>6.0'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'rake'
|
30
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
31
|
+
spec.add_development_dependency 'pry'
|
32
|
+
spec.add_development_dependency 'pry-doc'
|
33
|
+
spec.add_development_dependency 'debug', '>= 1.0.0'
|
34
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
# Allow dates to blankify day, month, or year component
|
2
|
+
class BlankableDate < Date
|
3
|
+
cattr_accessor :blanks, :valid_styles, :default_style
|
4
|
+
|
5
|
+
self.default_style = :tex_dots
|
6
|
+
self.valid_styles = []
|
7
|
+
|
8
|
+
self.blanks = {}
|
9
|
+
blanks[:tex_dots] = {}
|
10
|
+
blanks[:tex_rules] = {}
|
11
|
+
blanks[:ascii_dots] = {}
|
12
|
+
blanks[:ascii_rules] = {}
|
13
|
+
|
14
|
+
#######################################################################
|
15
|
+
# Set blank styles
|
16
|
+
#######################################################################
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Use TeX \dotfill macro to represent blanks
|
20
|
+
def set_tex_dots
|
21
|
+
style = :tex_dots
|
22
|
+
valid_styles.push(style)
|
23
|
+
blanks[style][:long] = '\\leavevmode\\hbox to 9em{\\dotfill}}'
|
24
|
+
blanks[style][:medium] = '\\leavevmode\\hbox to 4em{\\dotfill}}'
|
25
|
+
blanks[style][:short] = '\\leavevmode\\hbox to 2em{\\dotfill}}'
|
26
|
+
end
|
27
|
+
|
28
|
+
# Use TeX \hrulefill macro to represent blanks
|
29
|
+
def set_tex_rules
|
30
|
+
style = :tex_rules
|
31
|
+
valid_styles.push(style)
|
32
|
+
blanks[style][:long] = '\\leavevmode\\hbox to 9em{\\hrulefill}}'
|
33
|
+
blanks[style][:medium] = '\\leavevmode\\hbox to 4em{\\hrulefill}}'
|
34
|
+
blanks[style][:short] = '\\leavevmode\\hbox to 2em{\\hrulefill}}'
|
35
|
+
end
|
36
|
+
|
37
|
+
# Use a series of acsii '.' to represent blanks
|
38
|
+
def set_ascii_dots
|
39
|
+
style = :ascii_dots
|
40
|
+
valid_styles.push(style)
|
41
|
+
blanks[style][:long] = '.........'
|
42
|
+
blanks[style][:medium] = '....'
|
43
|
+
blanks[style][:short] = '..'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Use a series of acsii '_' to represent blanks
|
47
|
+
def set_ascii_rules
|
48
|
+
style = :ascii_rules
|
49
|
+
valid_styles.push(style)
|
50
|
+
blanks[style][:long] = '_________'
|
51
|
+
blanks[style][:medium] = '____'
|
52
|
+
blanks[style][:short] = '__'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
set_tex_dots
|
57
|
+
set_tex_rules
|
58
|
+
set_ascii_dots
|
59
|
+
set_ascii_rules
|
60
|
+
end
|
61
|
+
|
62
|
+
class BlankableDate < Date
|
63
|
+
attr_reader :style
|
64
|
+
|
65
|
+
# Initialize a BlankableDate in the same way as Date.new but allow blank
|
66
|
+
# components to be declared with keyword arguments ~blank_day~, ~blank_month~,
|
67
|
+
# and ~blank_year~. By default, none of the components is blank, so a
|
68
|
+
# BlankableDate acts just like a Date. However, when converted to a string
|
69
|
+
# with #strftime, the blank components are replaced with strings representing
|
70
|
+
# blanks.
|
71
|
+
def self.new(year, month, day,
|
72
|
+
blank_day: false,
|
73
|
+
blank_month: false,
|
74
|
+
blank_year: false)
|
75
|
+
obj = super(year, month, day)
|
76
|
+
obj.instance_variable_set(:@day_blank, blank_day)
|
77
|
+
obj.instance_variable_set(:@month_blank, blank_month)
|
78
|
+
obj.instance_variable_set(:@year_blank, blank_year)
|
79
|
+
obj.instance_variable_set(:@style, default_style)
|
80
|
+
obj
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.parse(str)
|
84
|
+
dt = super
|
85
|
+
new(dt.year, dt.month, dt.day)
|
86
|
+
end
|
87
|
+
|
88
|
+
##########################################################################
|
89
|
+
# Constructors
|
90
|
+
##########################################################################
|
91
|
+
|
92
|
+
# Return today as a BlankableDate
|
93
|
+
def self.today
|
94
|
+
today = Date.today
|
95
|
+
new(today.year, today.month, today.day)
|
96
|
+
end
|
97
|
+
|
98
|
+
# A date this month with the day blank
|
99
|
+
def self.this_month
|
100
|
+
day = Date.today
|
101
|
+
new(day.year, day.month, day.day).blank_day
|
102
|
+
end
|
103
|
+
|
104
|
+
# A date this year with the month and day blank
|
105
|
+
def self.this_year
|
106
|
+
day = Date.today
|
107
|
+
new(day.year, day.month, day.day)
|
108
|
+
.blank_month
|
109
|
+
.blank_day
|
110
|
+
end
|
111
|
+
|
112
|
+
# A date last month with the day blank
|
113
|
+
def self.last_month
|
114
|
+
day = Date.today - 1.month
|
115
|
+
new(day.year, day.month, day.day).blank_day
|
116
|
+
end
|
117
|
+
|
118
|
+
# A date last year with the month and day blank
|
119
|
+
def self.last_year
|
120
|
+
day = Date.today
|
121
|
+
new(day.year - 1, day.month, day.day)
|
122
|
+
.blank_month
|
123
|
+
.blank_day
|
124
|
+
end
|
125
|
+
|
126
|
+
# A date next month with the day blank
|
127
|
+
def self.next_month
|
128
|
+
day = Date.today + 1.month
|
129
|
+
new(day.year, day.month, day.day)
|
130
|
+
.blank_day
|
131
|
+
end
|
132
|
+
|
133
|
+
# A date next year with the month and day blank
|
134
|
+
def self.next_year
|
135
|
+
day = Date.today
|
136
|
+
new(day.year + 1, day.month, day.day)
|
137
|
+
.blank_month
|
138
|
+
.blank_day
|
139
|
+
end
|
140
|
+
|
141
|
+
#######################################################################
|
142
|
+
# Blanking commands
|
143
|
+
#######################################################################
|
144
|
+
|
145
|
+
# Set the blank style for this BlankableDate.
|
146
|
+
def styled(style)
|
147
|
+
style = style.to_sym
|
148
|
+
unless self.class.valid_styles.include?(style)
|
149
|
+
raise ArgumentError, "invalid style: '#{style}'"
|
150
|
+
end
|
151
|
+
@style = style
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
# Set the day component blank
|
156
|
+
def blank_day
|
157
|
+
@day_blank = true
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
# Set the month component blank
|
162
|
+
def blank_month
|
163
|
+
@month_blank = true
|
164
|
+
self
|
165
|
+
end
|
166
|
+
|
167
|
+
# Set the year component blank
|
168
|
+
def blank_year
|
169
|
+
@year_blank = true
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
#######################################################################
|
174
|
+
# Query blank components
|
175
|
+
#######################################################################
|
176
|
+
|
177
|
+
# Return true if the day is blank
|
178
|
+
def day_blank?
|
179
|
+
@day_blank
|
180
|
+
end
|
181
|
+
|
182
|
+
# Return true if the month is blank
|
183
|
+
def month_blank?
|
184
|
+
@month_blank
|
185
|
+
end
|
186
|
+
|
187
|
+
# Return true if the year is blank
|
188
|
+
def year_blank?
|
189
|
+
@year_blank
|
190
|
+
end
|
191
|
+
|
192
|
+
def any_blank?
|
193
|
+
day_blank? || month_blank? || year_blank?
|
194
|
+
end
|
195
|
+
|
196
|
+
#######################################################################
|
197
|
+
# Formatting
|
198
|
+
#######################################################################
|
199
|
+
|
200
|
+
def strftime(fmt = '%F')
|
201
|
+
# Preserve literal percents
|
202
|
+
fmt = fmt.gsub(/%%/, '<++++>')
|
203
|
+
# Expand combinations
|
204
|
+
fmt = fmt.gsub(/%F/, '%Y-%m-%d') if fmt =~ /%F/
|
205
|
+
fmt = fmt.gsub(/%c/, '%a %b %e %T %Y') if fmt =~ /%c/
|
206
|
+
fmt = fmt.gsub(/%[Dx]/, '%m/%d/%y') if fmt =~ /%[Dx]/
|
207
|
+
fmt = fmt.gsub(/%v/, '%e-%b-%Y') if fmt =~ /%v/
|
208
|
+
fmt = fmt.gsub(/%\+/, '%a %b %e %H:%M:%S %Z %Y') if fmt =~ /%\+/
|
209
|
+
# Replace individual components
|
210
|
+
fmt = fmt.gsub(/%-?[ed]/, short_blank) if day_blank?
|
211
|
+
fmt = fmt.gsub(/%[-_]?m/, short_blank) if month_blank?
|
212
|
+
fmt = fmt.gsub(/%[y]/, short_blank) if year_blank?
|
213
|
+
fmt = fmt.gsub(/%^?[bh]/, medium_blank) if month_blank?
|
214
|
+
fmt = fmt.gsub(/%j/, medium_blank) if day_blank? || month_blank?
|
215
|
+
fmt = fmt.gsub(/%[Y]/, medium_blank) if year_blank?
|
216
|
+
fmt = fmt.gsub(/%^?B/, long_blank) if month_blank?
|
217
|
+
fmt = fmt.gsub(/%^?A/, long_blank) if any_blank?
|
218
|
+
fmt = fmt.gsub(/%^?a/, medium_blank) if any_blank?
|
219
|
+
fmt = fmt.gsub(/%[uw]/, short_blank) if any_blank?
|
220
|
+
fmt = fmt.gsub(/%C/, "#{(year / 100).floor}#{short_blank}") if year_blank?
|
221
|
+
# Restore literal percents
|
222
|
+
fmt = fmt.gsub('<++++>', '%%')
|
223
|
+
super(fmt)
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def short_blank
|
229
|
+
self.class.blanks[@style][:short]
|
230
|
+
end
|
231
|
+
|
232
|
+
def medium_blank
|
233
|
+
self.class.blanks[@style][:medium]
|
234
|
+
end
|
235
|
+
|
236
|
+
def long_blank
|
237
|
+
self.class.blanks[@style][:long]
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module LawDoc
|
2
|
+
class Address
|
3
|
+
attr_reader :street, :city, :state, :zip, :country
|
4
|
+
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
def initialize(street: nil, streets: nil, city: nil,
|
8
|
+
state: nil, zip: nil, country: 'United States')
|
9
|
+
street ||= streets
|
10
|
+
case street
|
11
|
+
when String
|
12
|
+
@street = [street.to_s]
|
13
|
+
when Array
|
14
|
+
@street = street.map(&:to_s)
|
15
|
+
end
|
16
|
+
@city = city
|
17
|
+
@state = state
|
18
|
+
@zip = zip.to_s
|
19
|
+
@country = country
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
{ street: street, city: city, state: state, zip: zip, country: country }
|
24
|
+
end
|
25
|
+
|
26
|
+
def <=>(other)
|
27
|
+
to_h <=> other.to_h
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return a TeX string with components separated by sep.
|
31
|
+
def tex_info(sep = ' ')
|
32
|
+
st = nil
|
33
|
+
st = street.map(&:tex_quote) if street && !street.empty?
|
34
|
+
[st, "#{@city.tex_quote}, #{@state.tex_quote} #{@zip.tex_quote}"]
|
35
|
+
.join(sep)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return a multi-line TeX string
|
39
|
+
def tex_block
|
40
|
+
tex_info("\\\\\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return an in-line TeX string
|
44
|
+
def tex_inline
|
45
|
+
tex_info(', ')
|
46
|
+
end
|
47
|
+
alias to_s tex_inline
|
48
|
+
end
|
49
|
+
end
|