card 1.18.0 → 1.18.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +20 -16
  4. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +1 -1
  5. data/db/schema.rb +110 -92
  6. data/lib/card.rb +1 -0
  7. data/lib/card/content.rb +4 -73
  8. data/lib/card/content/chunk.rb +119 -0
  9. data/lib/card/content/parser.rb +75 -0
  10. data/lib/card/diff.rb +25 -398
  11. data/lib/card/diff/lcs.rb +247 -0
  12. data/lib/card/diff/result.rb +131 -0
  13. data/lib/card/director_register.rb +5 -0
  14. data/lib/card/query/attributes.rb +19 -13
  15. data/lib/card/set/event.rb +2 -1
  16. data/lib/card/set_pattern.rb +4 -2
  17. data/lib/card/spec_helper.rb +7 -1
  18. data/lib/card/stage_director.rb +33 -5
  19. data/lib/card/subcards.rb +11 -3
  20. data/lib/card/subdirector_array.rb +14 -1
  21. data/lib/cardio.rb +8 -5
  22. data/mod/01_core/chunk/include.rb +2 -2
  23. data/mod/01_core/chunk/link.rb +3 -3
  24. data/mod/01_core/chunk/literal.rb +20 -14
  25. data/mod/01_core/chunk/query_reference.rb +2 -2
  26. data/mod/01_core/chunk/reference.rb +47 -38
  27. data/mod/01_core/chunk/uri.rb +17 -13
  28. data/mod/01_core/format/html_format.rb +0 -2
  29. data/mod/01_core/set/all/actify.rb +12 -1
  30. data/mod/01_core/set/all/collection.rb +4 -4
  31. data/mod/01_core/set/all/fetch.rb +0 -27
  32. data/mod/01_core/set/all/name.rb +33 -12
  33. data/mod/01_core/set/all/pattern.rb +2 -6
  34. data/mod/01_core/set/all/phases.rb +0 -1
  35. data/mod/01_core/set/all/references.rb +2 -2
  36. data/mod/01_core/set/all/rules.rb +10 -3
  37. data/mod/01_core/set/all/tracked_attributes.rb +0 -1
  38. data/mod/01_core/set/all/type.rb +0 -14
  39. data/mod/01_core/spec/chunk/literal_spec.rb +1 -1
  40. data/mod/01_core/spec/chunk/uri_spec.rb +204 -201
  41. data/mod/01_core/spec/set/all/type_spec.rb +3 -1
  42. data/mod/01_history/lib/card/action.rb +7 -9
  43. data/mod/01_history/set/all/history.rb +6 -1
  44. data/mod/02_basic_types/set/all/all_csv.rb +1 -1
  45. data/mod/02_basic_types/set/type/pointer.rb +20 -9
  46. data/mod/03_machines/lib/javascript/wagn.js.coffee +1 -1
  47. data/mod/04_settings/set/right/structure.rb +7 -1
  48. data/mod/05_email/set/right/follow.rb +22 -22
  49. data/mod/05_email/set/type_plus_right/user/follow.rb +25 -26
  50. data/mod/05_standard/set/all/rich_html/wrapper.rb +12 -6
  51. data/mod/05_standard/set/rstar/rules_editor.rb +6 -4
  52. data/mod/05_standard/set/self/all.rb +0 -10
  53. data/mod/05_standard/set/self/stats.rb +6 -15
  54. data/mod/05_standard/set/type/set.rb +0 -6
  55. data/mod/05_standard/spec/chunk/include_spec.rb +2 -2
  56. data/mod/05_standard/spec/chunk/link_spec.rb +1 -1
  57. data/mod/05_standard/spec/chunk/query_reference_spec.rb +5 -4
  58. data/spec/lib/card/chunk_spec.rb +7 -5
  59. data/spec/lib/card/content_spec.rb +11 -11
  60. data/spec/lib/card/diff_spec.rb +4 -4
  61. data/spec/lib/card/stage_director_spec.rb +56 -0
  62. data/spec/lib/card/subcards_spec.rb +0 -1
  63. data/spec/models/card/type_transition_spec.rb +5 -42
  64. metadata +12 -23
  65. data/lib/card/chunk.rb +0 -122
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8c446c5d4d4690dcdfd3dfec9e7ccd86eb8103d
4
- data.tar.gz: 46449abad4c318e46f01f1785d37d755bbdbcac8
3
+ metadata.gz: e0e96aef9fe8581d7e787b0ad6ed56db1b3ec7d1
4
+ data.tar.gz: bbdd504c7800d1c372bd4199a293eeeb4e0ad501
5
5
  SHA512:
6
- metadata.gz: ff2d853a9eb45e599c82338dc3b9b2bfae8674b38ff61129715bf2082311dc32aa323457d74cadee1ac87d0bad8d225787c403ed7bdbed94d69870b5f253af62
7
- data.tar.gz: c3f805c9e1eea8148e9567ef8fa2f89281a401c9c63677e2a06c5820871be6933bc094f83e3edf4dd43ba57025e193764708331f301b98b14925aec5ebe1f544
6
+ metadata.gz: 2bb8bfa7d9df016796744af64b3361c5abbf5fefe1b10d17f4ae08af370e12600e1e1353da8ed00ae07bc281c484a0fbf458fe51d535e06ff0b49fd2987d58a1
7
+ data.tar.gz: d0f7b44c9ec0b44118f29a0fab7721402fcdfb397df4396a914243aa5477e18eeefed973fcb1434eb56eb8af6c788104a59178f23fcf10c414b17b1394d4eb38
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.18.0
1
+ 1.18.1
data/card.gemspec CHANGED
@@ -1,25 +1,30 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = 'card'
5
- s.version = File.open(File.expand_path('../VERSION', __FILE__)).read.chomp
6
- s.authors = ['Ethan McCutchen', 'Lewis Hoffman', 'Gerry Gleason', "Philipp Kühl"]
7
- s.email = ['info@wagn.org']
4
+ s.name = 'card'
5
+ s.version = File.open(File.expand_path('../VERSION', __FILE__)).read.chomp
6
+ s.authors =
7
+ ['Ethan McCutchen', 'Lewis Hoffman', 'Gerry Gleason', "Philipp Kühl"]
8
+ s.email = ['info@wagn.org']
8
9
 
9
10
  # s.date = '2013-12-20'
10
11
  s.summary = 'an atomic, set-driven content engine'
11
- s.description = 'Cards are data atoms that are grouped into Sets to which Rules can apply. Cards can formatted with Views and transformed with Events.'
12
+ s.description =
13
+ 'Cards are data atoms grouped into Sets to which Rules can apply. '\
14
+ 'Cards can formatted with Views and transformed with Events.'
12
15
  s.homepage = 'http://wagn.org'
13
16
  s.license = 'GPL'
14
17
 
15
- s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+ s.files = `git ls-files`.split $INPUT_RECORD_SEPARATOR
16
19
 
17
20
  # add submodule files (seed data)
18
- `git submodule --quiet foreach pwd`.split($OUTPUT_RECORD_SEPARATOR).each do |submod_path|
21
+ morepaths = `git submodule --quiet foreach pwd`.split $OUTPUT_RECORD_SEPARATOR
22
+ morepaths.each do |submod_path|
19
23
  gem_root = File.expand_path File.dirname(__FILE__)
20
24
  relative_submod_path = submod_path.gsub "#{gem_root}/", ''
21
25
  Dir.chdir(submod_path) do
22
- s.files += `git ls-files`.split($OUTPUT_RECORD_SEPARATOR).map do |filename|
26
+ morefiles = `git ls-files`.split $OUTPUT_RECORD_SEPARATOR
27
+ s.files += morefiles.map do |filename|
23
28
  "#{relative_submod_path}/#{filename}"
24
29
  end
25
30
  end
@@ -31,15 +36,14 @@ Gem::Specification.new do |s|
31
36
  s.required_ruby_version = '>= 1.9.3'
32
37
 
33
38
  [
34
-
35
39
  ['smartname', '0.2.3'],
36
-
37
- ['activerecord-session_store', '~> 0.1'],
38
40
  ['uuid', '~> 2.3'],
39
- ['carrierwave', '~> 0.10'],
41
+ ['carrierwave', '~> 0.10'],
40
42
  ['htmlentities', '~> 4.3'],
41
- ['mini_magick', '~> 4.2.10'],
43
+ ['mini_magick', '~> 4.2'],
42
44
  ['recaptcha', '~> 0.4.0'],
45
+ # 0.4.0 is last version that doesn't require ruby 2.0
46
+
43
47
  ['coderay', '~> 1.0'],
44
48
  ['sass', '~> 3.2'],
45
49
  ['coffee-script', '~> 2.2'],
@@ -47,10 +51,10 @@ Gem::Specification.new do |s|
47
51
 
48
52
  ['haml', '~> 4.0'],
49
53
  ['kaminari', '~> 0.16'],
50
- ['bootstrap-kaminari-views', '~> 0.0.5'],
51
- ['diff-lcs', '~> 1.2']
52
54
 
55
+ ['bootstrap-kaminari-views', '~> 0'],
56
+ ['diff-lcs', '~> 1.2']
53
57
  ].each do |dep|
54
- s.add_runtime_dependency *dep
58
+ s.add_runtime_dependency(*dep)
55
59
  end
56
60
  end
@@ -57,7 +57,7 @@ class ImportBootstrapLayout < Card::CoreMigration
57
57
  # update layouts to have explicit views in nests
58
58
  Card.search(type_id: Card::LayoutTypeID) do |lcard|
59
59
  lcontent = Card::Content.new lcard.content, lcard
60
- lcontent.find_chunks(Card::Chunk::Include).each do |nest|
60
+ lcontent.find_chunks(Card::Content::Chunk::Include).each do |nest|
61
61
  nest.explicit_view = (nest.options[:inc_name] == '_main' ? 'open' : 'core')
62
62
  end
63
63
  lcard.update_attributes! content: lcontent.to_s
data/db/schema.rb CHANGED
@@ -11,121 +11,139 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20_160_122_153_608) do
15
- create_table 'card_actions', force: :cascade do |t|
16
- t.integer 'card_id', limit: 4
17
- t.integer 'card_act_id', limit: 4
18
- t.integer 'super_action_id', limit: 4
19
- t.integer 'action_type', limit: 4
20
- t.boolean 'draft'
21
- t.text 'comment', limit: 65_535
14
+ ActiveRecord::Schema.define(version: 20160122153608) do
15
+
16
+ create_table "card_actions", force: :cascade do |t|
17
+ t.integer "card_id", limit: 4
18
+ t.integer "card_act_id", limit: 4
19
+ t.integer "super_action_id", limit: 4
20
+ t.integer "action_type", limit: 4
21
+ t.boolean "draft"
22
+ t.text "comment", limit: 65535
22
23
  end
23
24
 
24
- add_index 'card_actions', ['card_act_id'], name: 'card_actions_card_act_id_index', using: :btree
25
- add_index 'card_actions', ['card_id'], name: 'card_actions_card_id_index', using: :btree
25
+ add_index "card_actions", ["card_act_id"], name: "card_actions_card_act_id_index", using: :btree
26
+ add_index "card_actions", ["card_id"], name: "card_actions_card_id_index", using: :btree
26
27
 
27
- create_table 'card_acts', force: :cascade do |t|
28
- t.integer 'card_id', limit: 4
29
- t.integer 'actor_id', limit: 4
30
- t.datetime 'acted_at'
31
- t.string 'ip_address', limit: 255
28
+ create_table "card_acts", force: :cascade do |t|
29
+ t.integer "card_id", limit: 4
30
+ t.integer "actor_id", limit: 4
31
+ t.datetime "acted_at"
32
+ t.string "ip_address", limit: 255
32
33
  end
33
34
 
34
- add_index 'card_acts', ['acted_at'], name: 'acts_acted_at_index', using: :btree
35
- add_index 'card_acts', ['actor_id'], name: 'card_acts_actor_id_index', using: :btree
36
- add_index 'card_acts', ['card_id'], name: 'card_acts_card_id_index', using: :btree
35
+ add_index "card_acts", ["acted_at"], name: "acts_acted_at_index", using: :btree
36
+ add_index "card_acts", ["actor_id"], name: "card_acts_actor_id_index", using: :btree
37
+ add_index "card_acts", ["card_id"], name: "card_acts_card_id_index", using: :btree
37
38
 
38
- create_table 'card_changes', force: :cascade do |t|
39
- t.integer 'card_action_id', limit: 4
40
- t.integer 'field', limit: 4
41
- t.text 'value', limit: 16_777_215
39
+ create_table "card_changes", force: :cascade do |t|
40
+ t.integer "card_action_id", limit: 4
41
+ t.integer "field", limit: 4
42
+ t.text "value", limit: 16777215
42
43
  end
43
44
 
44
- add_index 'card_changes', ['card_action_id'], name: 'card_changes_card_action_id_index', using: :btree
45
+ add_index "card_changes", ["card_action_id"], name: "card_changes_card_action_id_index", using: :btree
45
46
 
46
- create_table 'card_references', force: :cascade do |t|
47
- t.integer 'referer_id', limit: 4, default: 0, null: false
48
- t.string 'referee_key', limit: 255, default: '', null: false
49
- t.integer 'referee_id', limit: 4
50
- t.string 'ref_type', limit: 1, default: '', null: false
51
- t.integer 'present', limit: 4
47
+ create_table "card_references", force: :cascade do |t|
48
+ t.integer "referer_id", limit: 4, default: 0, null: false
49
+ t.string "referee_key", limit: 255, default: "", null: false
50
+ t.integer "referee_id", limit: 4
51
+ t.string "ref_type", limit: 1, default: "", null: false
52
+ t.integer "present", limit: 4
52
53
  end
53
54
 
54
- add_index 'card_references', ['ref_type'], name: 'card_references_ref_type_index', using: :btree
55
- add_index 'card_references', ['referee_id'], name: 'card_references_referee_id_index', using: :btree
56
- add_index 'card_references', ['referee_key'], name: 'card_references_referee_key_index', using: :btree
57
- add_index 'card_references', ['referer_id'], name: 'card_references_referer_id_index', using: :btree
55
+ add_index "card_references", ["ref_type"], name: "card_references_ref_type_index", using: :btree
56
+ add_index "card_references", ["referee_id"], name: "card_references_referee_id_index", using: :btree
57
+ add_index "card_references", ["referee_key"], name: "card_references_referee_key_index", using: :btree
58
+ add_index "card_references", ["referer_id"], name: "card_references_referer_id_index", using: :btree
58
59
 
59
- create_table 'card_revisions', force: :cascade do |t|
60
- t.datetime 'created_at', null: false
61
- t.integer 'card_id', limit: 4, null: false
62
- t.integer 'creator_id', limit: 4, null: false
63
- t.text 'content', limit: 65_535, null: false
60
+ create_table "card_revisions", force: :cascade do |t|
61
+ t.datetime "created_at", null: false
62
+ t.integer "card_id", limit: 4, null: false
63
+ t.integer "creator_id", limit: 4, null: false
64
+ t.text "content", limit: 65535, null: false
64
65
  end
65
66
 
66
- add_index 'card_revisions', ['card_id'], name: 'revisions_card_id_index', using: :btree
67
- add_index 'card_revisions', ['creator_id'], name: 'revisions_created_by_index', using: :btree
68
-
69
- create_table 'cards', force: :cascade do |t|
70
- t.string 'name', limit: 255, null: false
71
- t.string 'key', limit: 255, null: false
72
- t.string 'codename', limit: 255
73
- t.integer 'left_id', limit: 4
74
- t.integer 'right_id', limit: 4
75
- t.integer 'current_revision_id', limit: 4
76
- t.datetime 'created_at', null: false
77
- t.datetime 'updated_at', null: false
78
- t.integer 'creator_id', limit: 4, null: false
79
- t.integer 'updater_id', limit: 4, null: false
80
- t.string 'read_rule_class', limit: 255
81
- t.integer 'read_rule_id', limit: 4
82
- t.integer 'references_expired', limit: 4
83
- t.boolean 'trash', null: false
84
- t.integer 'type_id', limit: 4, null: false
85
- t.text 'db_content', limit: 16_777_215
67
+ add_index "card_revisions", ["card_id"], name: "revisions_card_id_index", using: :btree
68
+ add_index "card_revisions", ["creator_id"], name: "revisions_created_by_index", using: :btree
69
+
70
+ create_table "cards", force: :cascade do |t|
71
+ t.integer "left_id", limit: 4
72
+ t.datetime "created_at", null: false
73
+ t.datetime "updated_at", null: false
74
+ t.integer "current_revision_id", limit: 4
75
+ t.string "name", limit: 255, null: false
76
+ t.integer "creator_id", limit: 4, null: false
77
+ t.integer "updater_id", limit: 4, null: false
78
+ t.integer "right_id", limit: 4
79
+ t.string "key", limit: 255, null: false
80
+ t.boolean "trash", null: false
81
+ t.integer "references_expired", limit: 4
82
+ t.string "codename", limit: 255
83
+ t.string "read_rule_class", limit: 255
84
+ t.integer "read_rule_id", limit: 4
85
+ t.integer "type_id", limit: 4, null: false
86
+ t.text "db_content", limit: 16777215
86
87
  end
87
88
 
88
- add_index 'cards', ['created_at'], name: 'cards_created_at_index', using: :btree
89
- add_index 'cards', ['key'], name: 'cards_key_index', unique: true, using: :btree
90
- add_index 'cards', ['left_id'], name: 'cards_left_id_index', using: :btree
91
- add_index 'cards', ['name'], name: 'cards_name_index', using: :btree
92
- add_index 'cards', ['read_rule_id'], name: 'cards_read_rule_id_index', using: :btree
93
- add_index 'cards', ['right_id'], name: 'cards_right_id_index', using: :btree
94
- add_index 'cards', ['type_id'], name: 'cards_type_id_index', using: :btree
95
- add_index 'cards', ['updated_at'], name: 'cards_updated_at_index', using: :btree
96
-
97
- create_table 'schema_migrations_core_cards', id: false, force: :cascade do |t|
98
- t.string 'version', limit: 255, null: false
89
+ add_index "cards", ["created_at"], name: "cards_created_at_index", using: :btree
90
+ add_index "cards", ["key"], name: "cards_key_index", unique: true, using: :btree
91
+ add_index "cards", ["left_id"], name: "cards_left_id_index", using: :btree
92
+ add_index "cards", ["name"], name: "cards_name_index", using: :btree
93
+ add_index "cards", ["read_rule_id"], name: "cards_read_rule_id_index", using: :btree
94
+ add_index "cards", ["right_id"], name: "cards_right_id_index", using: :btree
95
+ add_index "cards", ["type_id"], name: "cards_type_id_index", using: :btree
96
+ add_index "cards", ["updated_at"], name: "cards_updated_at_index", using: :btree
97
+
98
+ create_table "delayed_jobs", force: :cascade do |t|
99
+ t.integer "priority", limit: 4, default: 0, null: false
100
+ t.integer "attempts", limit: 4, default: 0, null: false
101
+ t.text "handler", limit: 65535, null: false
102
+ t.text "last_error", limit: 65535
103
+ t.datetime "run_at"
104
+ t.datetime "locked_at"
105
+ t.datetime "failed_at"
106
+ t.string "locked_by", limit: 255
107
+ t.string "queue", limit: 255
108
+ t.datetime "created_at"
109
+ t.datetime "updated_at"
99
110
  end
100
111
 
101
- add_index 'schema_migrations_core_cards', ['version'], name: 'unique_schema_migrations_cards', unique: true, using: :btree
112
+ add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
102
113
 
103
- create_table 'schema_migrations_deck_cards', id: false, force: :cascade do |t|
104
- t.string 'version', limit: 255, null: false
114
+ create_table "schema_migrations_core_cards", id: false, force: :cascade do |t|
115
+ t.string "version", limit: 255, null: false
105
116
  end
106
117
 
107
- add_index 'schema_migrations_deck_cards', ['version'], name: 'unique_schema_migrations_deck_cards', unique: true, using: :btree
118
+ add_index "schema_migrations_core_cards", ["version"], name: "unique_schema_migrations_cards", unique: true, using: :btree
108
119
 
109
- create_table 'sessions', force: :cascade do |t|
110
- t.string 'session_id', limit: 255
111
- t.text 'data', limit: 65_535
112
- t.datetime 'updated_at'
120
+ create_table "schema_migrations_deck_cards", id: false, force: :cascade do |t|
121
+ t.string "version", limit: 255, null: false
113
122
  end
114
123
 
115
- add_index 'sessions', ['session_id'], name: 'sessions_session_id_index', using: :btree
116
-
117
- create_table 'users', force: :cascade do |t|
118
- t.string 'login', limit: 40
119
- t.string 'email', limit: 100
120
- t.string 'crypted_password', limit: 40
121
- t.string 'salt', limit: 42
122
- t.datetime 'created_at'
123
- t.datetime 'updated_at'
124
- t.string 'password_reset_code', limit: 40
125
- t.string 'status', limit: 255, default: 'request'
126
- t.integer 'invite_sender_id', limit: 4
127
- t.string 'identity_url', limit: 255
128
- t.integer 'card_id', limit: 4, null: false
129
- t.integer 'account_id', limit: 4, null: false
124
+ add_index "schema_migrations_deck_cards", ["version"], name: "unique_schema_migrations_deck_cards", unique: true, using: :btree
125
+
126
+ create_table "sessions", force: :cascade do |t|
127
+ t.string "session_id", limit: 255
128
+ t.text "data", limit: 65535
129
+ t.datetime "updated_at"
130
+ end
131
+
132
+ add_index "sessions", ["session_id"], name: "sessions_session_id_index", using: :btree
133
+
134
+ create_table "users", force: :cascade do |t|
135
+ t.string "login", limit: 40
136
+ t.string "email", limit: 100
137
+ t.string "crypted_password", limit: 40
138
+ t.string "salt", limit: 42
139
+ t.datetime "created_at"
140
+ t.datetime "updated_at"
141
+ t.string "password_reset_code", limit: 40
142
+ t.string "status", limit: 255, default: "request"
143
+ t.integer "invite_sender_id", limit: 4
144
+ t.string "identity_url", limit: 255
145
+ t.integer "card_id", limit: 4, null: false
146
+ t.integer "account_id", limit: 4, null: false
130
147
  end
148
+
131
149
  end
data/lib/card.rb CHANGED
@@ -35,6 +35,7 @@ class Card < ActiveRecord::Base
35
35
  require_dependency 'card/stage_director'
36
36
  require_dependency 'card/director_register'
37
37
 
38
+
38
39
  has_many :references_in, class_name: :Reference, foreign_key: :referee_id
39
40
  has_many :references_out, class_name: :Reference, foreign_key: :referer_id
40
41
  has_many :acts, -> { order :id }
data/lib/card/content.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- # TODO: move Card::Chunk to Card::Content::Chunk...
4
- require_dependency 'card/chunk'
3
+ require_dependency 'card/content/chunk'
4
+ require_dependency 'card/content/parser'
5
5
 
6
6
  class Card
7
7
  class Content < SimpleDelegator
@@ -16,8 +16,8 @@ class Card
16
16
  end
17
17
  @opts = opts || {}
18
18
 
19
- content = parse_content content unless content.is_a?(Array)
20
- super content
19
+ @chunks = Parser.new(chunk_list).parse(content, self)
20
+ super(@chunks.any? ? @chunks : content)
21
21
  end
22
22
 
23
23
  def card
@@ -62,75 +62,6 @@ class Card
62
62
  self
63
63
  end
64
64
 
65
- def parse_content content
66
- @chunks = []
67
-
68
- if content.is_a? String
69
- position = last_position = 0
70
- prefix_regexp = Chunk.get_prefix_regexp chunk_list
71
- interval_string = ''
72
-
73
- while (prefix_match = content[position..-1].match(prefix_regexp))
74
- prefix = prefix_match[0]
75
- # prefix of matched chunk
76
- chunk_start = prefix_match.begin(0) + position
77
- # content index of beginning of chunk
78
- if prefix_match.begin(0) > 0
79
- # if matched chunk is not beginning of test string
80
- interval_string += content[position..chunk_start - 1]
81
- # hold onto the non-chunk part of the string
82
- end
83
-
84
- chunk_class = Chunk.find_class_by_prefix prefix
85
- # get the chunk class from the prefix
86
- match, offset =
87
- chunk_class.full_match content[chunk_start..-1], prefix
88
- # see whether the full chunk actually matches
89
- # (as opposed to bogus prefix)
90
- context_ok = chunk_class.context_ok? content, chunk_start
91
- # make sure there aren't contextual reasons for ignoring this chunk
92
- position = chunk_start
93
- # move scanning position up to beginning of chunk
94
-
95
- if match
96
- # we have a chunk match
97
- position += (match.end(0) - offset.to_i)
98
- # move scanning position up to end of chunk
99
- if context_ok
100
- @chunks << interval_string unless interval_string.empty?
101
- # add the nonchunk string to the chunk list
102
- @chunks << chunk_class.new(match, self)
103
- # add the chunk to the chunk list
104
- interval_string = ''
105
- # reset interval string for next go-round
106
- last_position = position
107
- # note that the end of the chunk was the last place where a
108
- # chunk was found (so far)
109
- end
110
- else
111
- position += 1
112
- # no match. look at the next character
113
- end
114
-
115
- next unless !match || !context_ok
116
- interval_string += content[chunk_start..position - 1]
117
- # moving beyond the alleged chunk.
118
- # append failed string to "nonchunk" string
119
- end
120
- end
121
-
122
- if chunks.any?
123
- if last_position < content.size
124
- remainder = content[last_position..-1]
125
- # handle any leftover nonchunk string at the end of content
126
- @chunks << remainder
127
- end
128
- chunks
129
- else
130
- content
131
- end
132
- end
133
-
134
65
  ALLOWED_TAGS = {}
135
66
  %w(
136
67
  br i b pre cite caption strong em ins sup sub del ol hr ul li p
@@ -0,0 +1,119 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'uri/common'
4
+
5
+ class Card #::Content
6
+ class Content < SimpleDelegator
7
+ # A chunk is a pattern of text that can be protected
8
+ # and interrogated by a format. Each Chunk class has a
9
+ # +pattern+ that states what sort of text it matches.
10
+ # Chunks are initalized by passing in the result of a
11
+ # match by its pattern.
12
+ module Chunk
13
+ mattr_accessor :raw_list, :prefix_regexp_by_list, :prefix_map
14
+ @@raw_list = {}
15
+ @@prefix_regexp_by_list = {}
16
+ @@prefix_map = {}
17
+
18
+ class << self
19
+ def register_class klass, hash
20
+ klass.config = hash.merge class: klass
21
+ prefix_index = hash[:idx_char] || :default
22
+ # ^ this is gross and needs to be moved out.
23
+ prefix_map[prefix_index] = klass.config
24
+ end
25
+
26
+ def register_list key, list
27
+ raw_list[key] = list
28
+ end
29
+
30
+ def find_class_by_prefix prefix
31
+ config = prefix_map[prefix[0, 1]] ||
32
+ prefix_map[prefix[-1, 1]] ||
33
+ prefix_map[:default]
34
+ # prefix identified by first character, last character, or default.
35
+ # a little ugly...
36
+ config[:class]
37
+ end
38
+
39
+ def get_prefix_regexp chunk_list_key
40
+ prefix_regexp_by_list[chunk_list_key] ||= begin
41
+ prefix_res = raw_list[chunk_list_key].map do |chunkname|
42
+ chunk_class = const_get chunkname
43
+ chunk_class.config[:prefix_re]
44
+ end
45
+ /(?:#{ prefix_res * '|' })/m
46
+ end
47
+ end
48
+ end
49
+
50
+ # not sure whether this is best place. Could really happen almost anywhere
51
+ # (even before chunk classes are loaded).
52
+ register_list :default, [
53
+ :URI, :HostURI, :EmailURI, :EscapedLiteral, :Include, :Link
54
+ ]
55
+ register_list :references, [:EscapedLiteral, :Include, :Link]
56
+ register_list :nest_only, [:Include]
57
+ register_list :query, [:QueryReference]
58
+
59
+ class Abstract
60
+ class_attribute :config
61
+ attr_reader :text, :process_chunk
62
+
63
+ class << self
64
+ # if the prefix regex matched check that chunk against the full regex
65
+ def full_match content, prefix=nil
66
+ content.match full_re(prefix)
67
+ end
68
+
69
+ def full_re _prefix
70
+ config[:full_re]
71
+ end
72
+
73
+ def context_ok? _content, _chunk_start
74
+ true
75
+ end
76
+ end
77
+
78
+ def reference_code
79
+ 'I'
80
+ end
81
+
82
+ def initialize match, content
83
+ @text = match[0]
84
+ @processed = nil
85
+ @content = content
86
+ interpret match, content
87
+ self
88
+ end
89
+
90
+ def interpret _match_string, _content, _params
91
+ Rails.logger.info 'no #interpret method found for chunk class: ' \
92
+ "#{self.class}"
93
+ end
94
+
95
+ def format
96
+ @content.format
97
+ end
98
+
99
+ def card
100
+ @content.card
101
+ end
102
+
103
+ def to_s
104
+ @process_chunk || @processed || @text
105
+ end
106
+
107
+ def inspect
108
+ "<##{self.class}##{self}>"
109
+ end
110
+
111
+ def as_json _options={}
112
+ @process_chunk || @processed ||
113
+ "not rendered #{self.class}, #{card && card.name}"
114
+ end
115
+ end
116
+ end
117
+ end
118
+ Card::Loader.load_chunks
119
+ end