rticles 0.1.0 → 0.2.1

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YmI4M2E4YzI3Mjg0ZTFjNzI3NmY0YzU5YjliYWY1MWM1Y2UwZGRmYw==
4
+ YTcxY2YyZTYxMTYwOGFlNmJjYmQzZjI0YzFiMThjYmNkYTdhOGQ4MA==
5
5
  data.tar.gz: !binary |-
6
- NGViZjgyMzQ2ZDJmN2Y3OWY4MzBkMTdhNjIyNDAzOTdlNTBlNjc0Ng==
7
- !binary "U0hBNTEy":
6
+ NGQ3NDk4MjhkMmY3NGVlODRlNTI1NDAyMjNlYjU4NDM2ZTcwNWVkNA==
7
+ SHA512:
8
8
  metadata.gz: !binary |-
9
- MTJjZGM1OGYzYTNhNDFhODJiMzc4YTQ4NWNiOTFhMTMzMzAzMTdhNDBmMzE2
10
- OWUwMThhYzEyNjA3YWU0NTMwNjk3ZGQ2ZDc0NWU3ZDlmMmU5YjU4NmJhNTE2
11
- ODI1ZGYyYmRmM2QyNzFhNTJlZWE5ZGYwMmZlZDExZjA1YjliY2M=
9
+ ZWI5MDU0NDhlNTFkMWZhMjc4YmM0MDQ3MTc2ZjBhNWQxYTNjMzgxNDZkYmY2
10
+ ZDZiMWU4MjBkNTVmNjdkMTI0OWNiYmM5YzE3MWU5NTMxM2RiOTVlZDc5MTRm
11
+ YjJiMGMxNzJkMWM0OTEyOGM2M2U5OTUwZWY0OWNlNTdjZWY5Mjc=
12
12
  data.tar.gz: !binary |-
13
- ZTNkZjU2YWEyZjIwM2IyNzUxOTJhOTc2MDgyZDNlNTFiYTQ3NjMwN2Q4NWYy
14
- NjM0ZThjNWIwZmFiYzkxODc1MmU0ZjAzNGMxNjE4ZWNiNjE2YmEyMTZhOGM2
15
- ZDFjYWJmYjBkZDcwZmE4ZTQzZmFkYzA0N2EyZjg3OTRiMWE0OWI=
13
+ NjRiZDc3YWE4MTc3NWZiOGJiNjQ4ZDJhNGVmNzQwMzA4NThkMTQyZmU4OTgy
14
+ MzI2ZGM1Yjg5YzE1ZmQ4Y2MxODM5MDU4NjIxZjZlNTgyOTE3Nzc0MTlkMGI1
15
+ ODhkMDFmMjU0MjdlZTgyZTRiZGI3ODA2ZGM4YzRiMmM2YjQwN2Y=
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ before_script:
6
+ "pushd spec/dummy && RAILS_ENV=test bundle exec rake db:create db:migrate; popd"
7
+ notifications:
8
+ recipients:
9
+ - alerts@oneclickorgs.com
data/README.md CHANGED
@@ -11,7 +11,7 @@ License
11
11
  Rticles is licensed under the [GNU Affero General Public License, Version 3](http://www.fsf.org/licensing/licenses/agpl-3.0.html).
12
12
 
13
13
  Rticles
14
- Copyright (C) 2011, 2012 Circus Foundation
14
+ Copyright (C) 2011, 2012, 2013 Circus Foundation
15
15
 
16
16
  This program is free software: you can redistribute it and/or modify
17
17
  it under the terms of the GNU Affero General Public License as
@@ -8,6 +8,7 @@ module Rticles
8
8
  TOPIC_RE = /\A#rticles#topic#([A-Za-z_]+) /
9
9
  CONTINUATION_RE = /\A#rticles#continue /
10
10
  HEADING_RE = /\A#rticles#heading(#\d+|) /
11
+ LIST_RE = /\A#rticles#list /
11
12
 
12
13
  has_many :paragraphs, :order => 'position'
13
14
  has_many :top_level_paragraphs, :class_name => 'Paragraph', :order => 'position', :conditions => "parent_id IS NULL"
@@ -42,19 +43,21 @@ module Rticles
42
43
  if body
43
44
  o.push(for_display ? tlp.body_for_display({:insertions => insertions, :choices => choices}.merge(options)) : tlp.body)
44
45
  unless tlp.children.empty?
45
- o.push(sub_outline(tlp, options))
46
+ o.push(sub_outline(tlp, options.merge(list: tlp.list?)))
46
47
  end
47
48
  end
48
49
  end
49
50
  o
50
51
  end
51
52
 
52
- def to_html
53
+ def to_html(options={})
53
54
  html = "<section>"
54
55
  html += Rticles::Paragraph.generate_html(top_level_paragraphs,
55
- :insertions => insertions,
56
- :choices => choices,
57
- :numbering_config => numbering_config
56
+ {
57
+ :insertions => insertions,
58
+ :choices => choices,
59
+ :numbering_config => numbering_config
60
+ }.merge(options)
58
61
  )
59
62
  html += "</section>"
60
63
  html.html_safe
@@ -81,6 +84,7 @@ module Rticles
81
84
  topic = nil
82
85
  continuation = false
83
86
  heading = nil
87
+ list = false
84
88
 
85
89
  if name_match = text_or_sub_array.match(NAME_RE)
86
90
  text_or_sub_array = text_or_sub_array.sub(NAME_RE, '')
@@ -105,13 +109,20 @@ module Rticles
105
109
  heading = heading_match[1].sub(/\A#/, '').to_i
106
110
  end
107
111
  end
112
+
113
+ if text_or_sub_array.match(LIST_RE)
114
+ text_or_sub_array = text_or_sub_array.sub(LIST_RE, '')
115
+ list = true
116
+ end
117
+
108
118
  document.paragraphs.create(
109
119
  :parent_id => parent ? parent.id : nil,
110
120
  :body => text_or_sub_array,
111
121
  :name => name,
112
122
  :topic => topic,
113
123
  :heading => heading,
114
- :continuation => continuation
124
+ :continuation => continuation,
125
+ :list => list
115
126
  )
116
127
  when Array
117
128
  paragraphs_relation = parent ? parent.children : document.paragraphs.select{|p| p.parent_id.nil?}
@@ -134,9 +145,21 @@ module Rticles
134
145
  end
135
146
 
136
147
  def paragraph_numbers_for_topic(topic, consolidate=false)
137
- relevant_paragraphs = paragraphs.where(:topic => topic)
148
+ paragraph_numbers_for_topics([topic], consolidate)
149
+ end
150
+
151
+ def paragraph_numbers_for_topics(topics, consolidate=false)
152
+ relevant_paragraphs = paragraphs.where(:topic => topics)
138
153
  relevant_paragraphs = relevant_paragraphs.for_choices(choices)
139
- paragraph_numbers = relevant_paragraphs.map{|p| p.full_index(true, choices)}.select{|i| !i.nil?}.sort
154
+ # TODO Sorting by position won't work properly if the query includes
155
+ # sub-paragraphs, but it is fine for the common case where only
156
+ # top-level paragraphs have topics.
157
+ # We should really be sorting by full_index, but
158
+ # we don't have a sort function for this yet. (A naive typographical
159
+ # sort isn't good enough.)
160
+ relevant_paragraphs = relevant_paragraphs.order('position ASC')
161
+
162
+ paragraph_numbers = relevant_paragraphs.map{|p| p.full_index(true, choices)}.select{|i| !i.nil?}
140
163
 
141
164
  if consolidate
142
165
  consolidate_paragraph_numbers(paragraph_numbers)
@@ -152,7 +175,7 @@ module Rticles
152
175
  protected
153
176
 
154
177
  def consolidate_paragraph_numbers(numbers)
155
- numbers = numbers.sort
178
+ # numbers = numbers.sort
156
179
  consolidated_numbers = []
157
180
  current_run = []
158
181
  numbers.each do |n|
@@ -185,7 +208,8 @@ module Rticles
185
208
  for_display = options[:for_display]
186
209
 
187
210
  o = []
188
- p.children.each do |c|
211
+ last_index = p.children.length - 1
212
+ p.children.each_with_index do |c, index|
189
213
  body = for_display ? c.body_for_display({:insertions => insertions, :choices => choices}.merge(options)) : c.body
190
214
  if body
191
215
  o.push(body)
@@ -194,6 +218,20 @@ module Rticles
194
218
  end
195
219
  end
196
220
  end
221
+ if options[:list]
222
+ # Add terminating punctuation to the String elements of o, but making the last one a full stop instead of a semicolon.
223
+ final_element = true
224
+ o.reverse_each do |p|
225
+ if p.is_a?(String)
226
+ if final_element
227
+ p.sub!(/\Z/, '.')
228
+ final_element = false
229
+ else
230
+ p.sub!(/\Z/, ';')
231
+ end
232
+ end
233
+ end
234
+ end
197
235
  o
198
236
  end
199
237
  end
@@ -12,6 +12,7 @@ module Rticles
12
12
 
13
13
  def create_migration
14
14
  migration_template 'create_documents_and_paragraphs.rb', 'db/migrate/create_documents_and_paragraphs.rb'
15
+ migration_template 'add_list_to_paragraphs.rb', 'db/migrate/add_list_to_paragraphs.rb'
15
16
  end
16
17
  end
17
18
  end
@@ -0,0 +1,9 @@
1
+ class AddListToParagraphs < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :paragraphs, :list, :boolean
4
+ end
5
+
6
+ def self.down
7
+ remove_column :paragraphs, :list
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module Rticles
2
+ module Generators
3
+ class UpdateGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def self.next_migration_number(dirname)
9
+ next_migration_number = current_migration_number(dirname) + 1
10
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
11
+ end
12
+
13
+ def create_migration
14
+ migration_template 'add_list_to_paragraphs.rb', 'db/migrate/add_list_to_paragraphs.rb'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,7 +3,9 @@ require 'acts_as_list'
3
3
  module Rticles
4
4
  class Paragraph < ActiveRecord::Base
5
5
  attr_accessible :body, :parent_id, :after_id, :position, :before_id, :heading, :continuation,
6
- :name, :topic
6
+ :name, :topic, :list
7
+
8
+ attr_writer :choices
7
9
 
8
10
  belongs_to :document
9
11
  belongs_to :parent, :class_name => 'Paragraph'
@@ -14,7 +16,7 @@ module Rticles
14
16
  scope :for_choices, lambda {|choices|
15
17
  choices_condition = ["", {}]
16
18
  choices.each do |k, v|
17
- choices_condition[0] += "AND body NOT LIKE :#{k}"
19
+ choices_condition[0] += "AND body NOT LIKE :#{k} "
18
20
  choices_condition[1][k.to_sym] = "#rticles##{v ? 'false' : 'true'}##{k}%"
19
21
  end
20
22
  choices_condition[0].sub!(/\AAND /, '')
@@ -206,7 +208,7 @@ module Rticles
206
208
  string.gsub(insertion_re) do |match|
207
209
  insertion_name = match.sub('#rticles#', '')
208
210
  if insertions[insertion_name].present?
209
- insertions[insertion_name]
211
+ insertions[insertion_name].to_s.gsub("\n", "<br>")
210
212
  else
211
213
  "[#{insertion_name.humanize.upcase}]"
212
214
  end
@@ -249,11 +251,36 @@ module Rticles
249
251
 
250
252
  def self.generate_html_for_paragraph_groups(paragraph_groups, options={})
251
253
  previous_type = nil
252
- html = paragraph_groups.inject("") do |memo, paragraph_group|
254
+
255
+ # Remove paragraph groups that should not be displayed, given the choices that have been passed in
256
+ paragraph_groups = paragraph_groups.map do |pg|
257
+ first_paragraph = pg[0]
258
+ first_paragraph.choices = options[:choices]
259
+ if first_paragraph.resolve_choices(first_paragraph.body)
260
+ pg
261
+ else
262
+ nil
263
+ end
264
+ end
265
+ paragraph_groups = paragraph_groups.compact
266
+
267
+ # Handle last paragraph group separately so we can do list punctuation if necessary.
268
+
269
+ paragraph_groups_except_last = paragraph_groups[0..-2]
270
+ last_paragraph_group = paragraph_groups[-1]
271
+
272
+ html = paragraph_groups_except_last.inject("") do |memo, paragraph_group|
253
273
  # FIXME: Don't generate HTML by interpolating into a string;
254
274
  # use some standard library function that provides some safe
255
275
  # escaping defaults, etc..
256
- if paragraph_group.first.heading?
276
+
277
+ if options[:list]
278
+ options[:list_punctuation] = ';'
279
+ end
280
+
281
+ first_paragraph = paragraph_group[0]
282
+
283
+ if first_paragraph.heading?
257
284
  if previous_type == :paragraph
258
285
  memo += "</ol>"
259
286
  end
@@ -267,11 +294,42 @@ module Rticles
267
294
  unless previous_type == :paragraph
268
295
  memo += "<ol>"
269
296
  end
270
- memo += "<li>#{generate_html_for_paragraphs(paragraph_group, options)}</li>"
297
+ index = first_paragraph.index(options[:choices])
298
+ li_opening_tag = "<li value=\"#{index}\">"
299
+ memo += "#{li_opening_tag}#{generate_html_for_paragraphs(paragraph_group, options)}</li>"
271
300
  previous_type = :paragraph
272
301
  end
302
+
273
303
  memo
274
304
  end
305
+
306
+ # Process final paragraph group
307
+ if options[:list]
308
+ options[:list_punctuation] = '.'
309
+ end
310
+
311
+ first_paragraph = last_paragraph_group[0]
312
+
313
+ if first_paragraph.heading?
314
+ if previous_type == :paragraph
315
+ html += "</ol>"
316
+ end
317
+ if last_paragraph_group.length == 1
318
+ html += generate_html_for_paragraphs(last_paragraph_group, options)
319
+ else
320
+ html += "<hgroup>#{generate_html_for_paragraphs(last_paragraph_group, options)}</hgroup>"
321
+ end
322
+ previous_type = :heading
323
+ else
324
+ unless previous_type == :paragraph
325
+ html += "<ol>"
326
+ end
327
+ index = first_paragraph.index(options[:choices])
328
+ li_opening_tag = "<li value=\"#{index}\">"
329
+ html += "#{li_opening_tag}#{generate_html_for_paragraphs(last_paragraph_group, options)}</li>"
330
+ previous_type = :paragraph
331
+ end
332
+
275
333
  if previous_type == :paragraph
276
334
  html += "</ol>"
277
335
  end
@@ -283,13 +341,13 @@ module Rticles
283
341
  return memo if body.nil?
284
342
 
285
343
  if paragraph.heading?
286
- memo += "<h#{paragraph.heading_level}>#{body}</h#{paragraph.heading_level}>"
344
+ memo += "<h#{paragraph.heading_level}>#{body}#{options[:list_punctuation]}</h#{paragraph.heading_level}>"
287
345
  else
288
- memo += body
346
+ memo += "#{body}#{options[:list_punctuation]}"
289
347
  end
290
348
 
291
349
  if !paragraph.children.empty?
292
- memo += generate_html(paragraph.children, options)
350
+ memo += generate_html(paragraph.children, options.merge(list: paragraph.list?, list_punctuation: nil))
293
351
  end
294
352
  memo
295
353
  end
@@ -1,5 +1,6 @@
1
1
  class Rticles::Railtie < Rails::Railtie
2
2
  generators do
3
3
  require 'rticles/generators/install_generator'
4
+ require 'rticles/generators/update_generator'
4
5
  end
5
6
  end
@@ -1,3 +1,3 @@
1
1
  module Rticles
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -12,15 +12,17 @@ Gem::Specification.new do |s|
12
12
  s.homepage = "https://github.com/oneclickorgs/rticles"
13
13
  s.summary = "Consistent editing for legal documents."
14
14
  s.description = "Rticles is a Rails plugin that allows for web-based editing of legal documents. It lets you create nested, numbered paragraphs, along with intra-document references that remain accurate as paragraphs are inserted, removed and moved."
15
+ s.licenses = ['AGPL-3']
15
16
 
16
17
  s.files = `git ls-files`.split($\)
17
18
 
18
19
  s.add_dependency "rails", "~> 3.2.8"
19
- s.add_dependency "acts_as_list", "~>0.1.8"
20
+ s.add_dependency "acts_as_list", ">=0.1.8", "<0.3.0"
20
21
  s.add_dependency "roman-numerals", "~>0.3.0"
21
22
 
22
23
  s.add_development_dependency "sqlite3"
23
24
  s.add_development_dependency "rspec-rails"
24
25
  s.add_development_dependency "nokogiri"
25
26
  s.add_development_dependency "equivalent-xml"
27
+ s.add_development_dependency "coveralls"
26
28
  end
@@ -124,6 +124,73 @@ describe Rticles::Document do
124
124
  end
125
125
  end
126
126
 
127
+ describe "list punctuation" do
128
+ before(:each) do
129
+ yaml = File.open('spec/fixtures/list_termination.yml', 'r')
130
+ @document = Rticles::Document.from_yaml(yaml)
131
+ @document.save!
132
+
133
+ @document.choices = {
134
+ users: true,
135
+ employees: true,
136
+ supporters: true,
137
+ }
138
+ end
139
+
140
+ it "punctuates lists of sub-clauses correctly when all sub-clauses are present" do
141
+ expect(@document.outline(for_display: true)).to eq([
142
+ "The Board shall consist of:",
143
+ [
144
+ "Users;",
145
+ "Employees;",
146
+ "Supporters."
147
+ ]
148
+ ])
149
+ end
150
+
151
+ it "punctuates lists of sub-clauses correctly when some sub-clauses are omitted" do
152
+ @document.choices = {
153
+ users: true,
154
+ employees: true,
155
+ supporters: false
156
+ }
157
+
158
+ expect(@document.outline(for_display: true)).to eq([
159
+ "The Board shall consist of:",
160
+ [
161
+ "Users;",
162
+ "Employees."
163
+ ]
164
+ ])
165
+ end
166
+
167
+ it "punctuates lists correctly when generating HTML" do
168
+ @document.choices = {
169
+ users: true,
170
+ employees: true,
171
+ supporters: false
172
+ }
173
+
174
+ expected_html = <<-EOF
175
+ <section>
176
+ <ol>
177
+ <li value="1">
178
+ The Board shall consist of:
179
+ <ol>
180
+ <li value="1">Users;</li>
181
+ <li value="2">Employees.</li>
182
+ </ol>
183
+ </li>
184
+ </ol>
185
+ </section>
186
+ EOF
187
+
188
+ html = @document.to_html(with_index: false)
189
+
190
+ expect(html).to be_equivalent_to(expected_html)
191
+ end
192
+ end
193
+
127
194
  describe "topic lookup" do
128
195
  it "takes into account the current choices" do
129
196
  @document = Rticles::Document.create
@@ -151,6 +218,17 @@ describe Rticles::Document do
151
218
  @document.choices[:single_shareholding] = false
152
219
  @document.paragraph_numbers_for_topic('shares', true).should eq "35–40"
153
220
  end
221
+
222
+ it "can handle multiple topics" do
223
+ @document = Rticles::Document.create
224
+ @document.top_level_paragraphs.create(:body => "First shares rule", :topic => 'shares')
225
+ @document.top_level_paragraphs.create(:body => "Objectives rule", :topic => 'objectives')
226
+ @document.top_level_paragraphs.create(:body => "Other rule")
227
+ @document.top_level_paragraphs.create(:body => "Second shares rule", :topic => 'shares')
228
+
229
+ @document.paragraph_numbers_for_topics(['shares', 'objectives'], true).should eq '1–2, 4'
230
+ end
231
+
154
232
  end
155
233
 
156
234
  describe "numbering config" do
@@ -4,7 +4,7 @@
4
4
  = content_tag("h#{paragraph.heading_level}") do
5
5
  = paragraph.body_for_display
6
6
  - else
7
- = simple_format(paragraph.full_index + ' ' + paragraph.body_for_display)
7
+ = simple_format((paragraph.full_index || '') + ' ' + (paragraph.body_for_display || ''))
8
8
  - if @editing
9
9
  %p.control
10
10
  = link_to "Edit", edit_document_paragraph_path(:document_id => paragraph.document, :id => paragraph), :class => 'edit_paragraph'
@@ -1,6 +1,6 @@
1
1
  # Be sure to restart your server when you modify this file.
2
2
 
3
- Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
3
+ Dummy::Application.config.session_store :cookie_store, :key => '_dummy_session'
4
4
 
5
5
  # Use the database for sessions instead of the cookie-based default,
6
6
  # which shouldn't be used to store highly confidential information
@@ -5,7 +5,7 @@
5
5
 
6
6
  # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
7
  ActiveSupport.on_load(:action_controller) do
8
- wrap_parameters format: [:json]
8
+ wrap_parameters :format => [:json]
9
9
  end
10
10
 
11
11
  # Disable root element in JSON by default.
@@ -0,0 +1,9 @@
1
+ class AddListToParagraphs < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :paragraphs, :list, :boolean
4
+ end
5
+
6
+ def self.down
7
+ remove_column :paragraphs, :list
8
+ end
9
+ end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20120828203449) do
14
+ ActiveRecord::Schema.define(:version => 20140112165306) do
15
15
 
16
16
  create_table "documents", :force => true do |t|
17
17
  t.string "title"
@@ -30,6 +30,7 @@ ActiveRecord::Schema.define(:version => 20120828203449) do
30
30
  t.string "topic"
31
31
  t.datetime "created_at", :null => false
32
32
  t.datetime "updated_at", :null => false
33
+ t.boolean "list"
33
34
  end
34
35
 
35
36
  end
@@ -0,0 +1,5 @@
1
+ - "#rticles#list The Board shall consist of:"
2
+ -
3
+ - "#rticles#true#users Users"
4
+ - "#rticles#true#employees Employees"
5
+ - "#rticles#true#supporters Supporters"
@@ -224,21 +224,21 @@ describe Rticles::Paragraph do
224
224
  <h2>For demonstration purposes only</h2>
225
225
  </hgroup>
226
226
  <ol>
227
- <li>1 This is the first rule.</li>
228
- <li>
227
+ <li value="1">1 This is the first rule.</li>
228
+ <li value="2">
229
229
  2 This is the second rule, which applies when:
230
230
  <ol>
231
- <li>2.1 This condition;</li>
232
- <li>2.2 and this condition.</li>
231
+ <li value="1">2.1 This condition;</li>
232
+ <li value="2">2.2 and this condition.</li>
233
233
  </ol>
234
234
  except when it is a Full Moon.
235
235
  </li>
236
- <li>3 This is the third rule.</li>
237
- <li>4 This is the fourth rule.</li>
236
+ <li value="3">3 This is the third rule.</li>
237
+ <li value="4">4 This is the fourth rule.</li>
238
238
  </ol>
239
239
  <h2>And finally...</h2>
240
240
  <ol>
241
- <li>5 This is the final rule.</li>
241
+ <li value="5">5 This is the final rule.</li>
242
242
  </ol>
243
243
  </section>
244
244
  EOF
@@ -247,5 +247,159 @@ describe Rticles::Paragraph do
247
247
 
248
248
  html.should be_equivalent_to(expected_html)
249
249
  end
250
+
251
+ context "with insertions" do
252
+ it "converts newlines into br tags" do
253
+ @document.top_level_paragraphs.create(
254
+ :body => "A custom rule is: #rticles#custom_rule",
255
+ :after_id => @document.top_level_paragraphs.all[4].id
256
+ )
257
+
258
+ expected_html = <<-EOF
259
+ <section>
260
+ <hgroup>
261
+ <h1>A Simple Constitution</h1>
262
+ <h2>For demonstration purposes only</h2>
263
+ </hgroup>
264
+ <ol>
265
+ <li value="1">1 This is the first rule.</li>
266
+ <li value="2">
267
+ 2 This is the second rule, which applies when:
268
+ <ol>
269
+ <li value="1">2.1 This condition;</li>
270
+ <li value="2">2.2 and this condition.</li>
271
+ </ol>
272
+ except when it is a Full Moon.
273
+ </li>
274
+ <li value="3">3 A custom rule is: I can format my clauses<br>how I<br>please.</li>
275
+ <li value="4">4 This is the third rule.</li>
276
+ <li value="5">5 This is the fourth rule.</li>
277
+ </ol>
278
+ <h2>And finally...</h2>
279
+ <ol>
280
+ <li value="6">6 This is the final rule.</li>
281
+ </ol>
282
+ </section>
283
+ EOF
284
+
285
+ @document.insertions = {:custom_rule => "I can format my clauses\nhow I\nplease."}
286
+
287
+ html = @document.to_html
288
+
289
+ html.should be_equivalent_to(expected_html)
290
+ end
291
+ end
292
+
293
+ context "with choices" do
294
+ before(:each) do
295
+ @document.top_level_paragraphs.create(
296
+ :body => "#rticles#true#free_cake All members shall be entitled to free cake",
297
+ :after_id => @document.top_level_paragraphs.all[4].id
298
+ )
299
+ end
300
+
301
+ it "includes the 'true' clause when the choice is set to true" do
302
+ expected_html = <<-EOF
303
+ <section>
304
+ <hgroup>
305
+ <h1>A Simple Constitution</h1>
306
+ <h2>For demonstration purposes only</h2>
307
+ </hgroup>
308
+ <ol>
309
+ <li value="1">1 This is the first rule.</li>
310
+ <li value="2">
311
+ 2 This is the second rule, which applies when:
312
+ <ol>
313
+ <li value="1">2.1 This condition;</li>
314
+ <li value="2">2.2 and this condition.</li>
315
+ </ol>
316
+ except when it is a Full Moon.
317
+ </li>
318
+ <li value="3">3 All members shall be entitled to free cake</li>
319
+ <li value="4">4 This is the third rule.</li>
320
+ <li value="5">5 This is the fourth rule.</li>
321
+ </ol>
322
+ <h2>And finally...</h2>
323
+ <ol>
324
+ <li value="6">6 This is the final rule.</li>
325
+ </ol>
326
+ </section>
327
+ EOF
328
+
329
+ @document.choices = {:free_cake => true}
330
+
331
+ html = @document.to_html
332
+
333
+ html.should be_equivalent_to(expected_html)
334
+ end
335
+
336
+ it "excludes the 'true' clause when the choice is set to false" do
337
+ expected_html = <<-EOF
338
+ <section>
339
+ <hgroup>
340
+ <h1>A Simple Constitution</h1>
341
+ <h2>For demonstration purposes only</h2>
342
+ </hgroup>
343
+ <ol>
344
+ <li value="1">1 This is the first rule.</li>
345
+ <li value="2">
346
+ 2 This is the second rule, which applies when:
347
+ <ol>
348
+ <li value="1">2.1 This condition;</li>
349
+ <li value="2">2.2 and this condition.</li>
350
+ </ol>
351
+ except when it is a Full Moon.
352
+ </li>
353
+ <li value="3">3 This is the third rule.</li>
354
+ <li value="4">4 This is the fourth rule.</li>
355
+ </ol>
356
+ <h2>And finally...</h2>
357
+ <ol>
358
+ <li value="5">5 This is the final rule.</li>
359
+ </ol>
360
+ </section>
361
+ EOF
362
+
363
+ @document.choices = {:free_cake => false}
364
+
365
+ html = @document.to_html
366
+
367
+ html.should be_equivalent_to(expected_html)
368
+ end
369
+ end
370
+
371
+ context "without indexes" do
372
+ it "works" do
373
+ expected_html = <<-EOF
374
+ <section>
375
+ <hgroup>
376
+ <h1>A Simple Constitution</h1>
377
+ <h2>For demonstration purposes only</h2>
378
+ </hgroup>
379
+ <ol>
380
+ <li value="1">This is the first rule.</li>
381
+ <li value="2">
382
+ This is the second rule, which applies when:
383
+ <ol>
384
+ <li value="1">This condition;</li>
385
+ <li value="2">and this condition.</li>
386
+ </ol>
387
+ except when it is a Full Moon.
388
+ </li>
389
+ <li value="3">This is the third rule.</li>
390
+ <li value="4">This is the fourth rule.</li>
391
+ </ol>
392
+ <h2>And finally...</h2>
393
+ <ol>
394
+ <li value="5">This is the final rule.</li>
395
+ </ol>
396
+ </section>
397
+ EOF
398
+
399
+ html = @document.to_html(:with_index => false)
400
+
401
+ html.should be_equivalent_to(expected_html)
402
+ end
403
+ end
250
404
  end
251
405
  end
@@ -1,3 +1,6 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
1
4
  # This file is copied to spec/ when you run 'rails generate rspec:install'
2
5
  ENV["RAILS_ENV"] ||= 'test'
3
6
  require File.expand_path("../dummy/config/environment", __FILE__)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rticles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Mear
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-01 00:00:00.000000000 Z
11
+ date: 2014-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -28,16 +28,22 @@ dependencies:
28
28
  name: acts_as_list
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.1.8
34
+ - - <
35
+ - !ruby/object:Gem::Version
36
+ version: 0.3.0
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - ~>
41
+ - - ! '>='
39
42
  - !ruby/object:Gem::Version
40
43
  version: 0.1.8
44
+ - - <
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.0
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: roman-numerals
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +114,20 @@ dependencies:
108
114
  - - ! '>='
109
115
  - !ruby/object:Gem::Version
110
116
  version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: coveralls
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
111
131
  description: Rticles is a Rails plugin that allows for web-based editing of legal
112
132
  documents. It lets you create nested, numbered paragraphs, along with intra-document
113
133
  references that remain accurate as paragraphs are inserted, removed and moved.
@@ -119,6 +139,7 @@ extra_rdoc_files: []
119
139
  files:
120
140
  - .gitignore
121
141
  - .rspec
142
+ - .travis.yml
122
143
  - Gemfile
123
144
  - Gemfile.lock
124
145
  - LICENSE.txt
@@ -128,7 +149,9 @@ files:
128
149
  - lib/rticles.rb
129
150
  - lib/rticles/document.rb
130
151
  - lib/rticles/generators/install_generator.rb
152
+ - lib/rticles/generators/templates/add_list_to_paragraphs.rb
131
153
  - lib/rticles/generators/templates/create_documents_and_paragraphs.rb
154
+ - lib/rticles/generators/update_generator.rb
132
155
  - lib/rticles/numbering.rb
133
156
  - lib/rticles/paragraph.rb
134
157
  - lib/rticles/railtie.rb
@@ -179,6 +202,7 @@ files:
179
202
  - spec/dummy/config/locales/en.yml
180
203
  - spec/dummy/config/routes.rb
181
204
  - spec/dummy/db/migrate/20120828203449_create_documents_and_paragraphs.rb
205
+ - spec/dummy/db/migrate/20140112165306_add_list_to_paragraphs.rb
182
206
  - spec/dummy/db/schema.rb
183
207
  - spec/dummy/lib/assets/.gitkeep
184
208
  - spec/dummy/log/.gitkeep
@@ -189,13 +213,15 @@ files:
189
213
  - spec/dummy/script/rails
190
214
  - spec/fixtures/constitution.yml
191
215
  - spec/fixtures/ips.yml
216
+ - spec/fixtures/list_termination.yml
192
217
  - spec/fixtures/simple.yml
193
218
  - spec/paragraph_spec.rb
194
219
  - spec/spec_helper.rb
195
220
  - spec/support/custom_matchers.rb
196
221
  - spec/support/document_macros.rb
197
222
  homepage: https://github.com/oneclickorgs/rticles
198
- licenses: []
223
+ licenses:
224
+ - AGPL-3
199
225
  metadata: {}
200
226
  post_install_message:
201
227
  rdoc_options: []
@@ -213,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
239
  version: '0'
214
240
  requirements: []
215
241
  rubyforge_project:
216
- rubygems_version: 2.0.3
242
+ rubygems_version: 2.2.2
217
243
  signing_key:
218
244
  specification_version: 4
219
245
  summary: Consistent editing for legal documents.