card 1.18.0 → 1.18.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -68,7 +68,8 @@ class Card
68
68
  def define_event_method event, call_method, _opts
69
69
  class_eval do
70
70
  define_method event do
71
- # puts "#{name}:#{event}".green
71
+ # puts "#{name}:#{event}".red
72
+ # puts "#{Card::DirectorRegister.to_s}".green
72
73
  run_callbacks event do
73
74
  send call_method
74
75
  end
@@ -94,7 +94,8 @@ EOF
94
94
  if self.class.anchorless?
95
95
  self.class.pattern_code.camelize
96
96
  elsif anchor_codenames
97
- "#{self.class.pattern_code.camelize}::#{anchor_codenames.map(&:to_s).map(&:camelize) * '::'}"
97
+ codenames = [self.class.pattern_code] + anchor_codenames.map(&:to_s)
98
+ codenames.map(&:camelize).join '::'
98
99
  end
99
100
  end
100
101
  end
@@ -108,7 +109,8 @@ EOF
108
109
  end
109
110
 
110
111
  def format_module_list klass
111
- (hash = Card::Set.modules[:nonbase_format][klass]) && lookup_module_list(hash)
112
+ hash = Card::Set.modules[:nonbase_format][klass]
113
+ hash && lookup_module_list(hash)
112
114
  end
113
115
 
114
116
  def anchor_codenames
@@ -89,7 +89,13 @@ module Card::SpecHelper
89
89
  stage_sym = :"#{stage}_stage"
90
90
  $rspec_binding = binding
91
91
  add_test_event stage_sym, :in_stage_test, &event_block
92
- opts[:trigger].call
92
+ trigger =
93
+ if opts[:trigger].is_a?(Symbol)
94
+ method(opts[:trigger])
95
+ else
96
+ opts[:trigger]
97
+ end
98
+ trigger.call
93
99
  ensure
94
100
  remove_test_event stage_sym, :in_stage_test
95
101
  end
@@ -42,7 +42,10 @@ class Card
42
42
  def initialize card, opts={}, main=true
43
43
  @card = card
44
44
  @card.director = self
45
- @card.prepare_for_phases
45
+ # for read actions there is no validation phase
46
+ # so we have to set the action here
47
+ @card.identify_action
48
+
46
49
  @stage = nil
47
50
  @running = false
48
51
  @parent = opts[:parent]
@@ -58,15 +61,22 @@ class Card
58
61
  end
59
62
 
60
63
  def unregister
64
+ Card::DirectorRegister.delete self
65
+ end
66
+
67
+ def delete
61
68
  @card.director = nil
62
- @subdirectors = nil
69
+ @subdirectors.clear
63
70
  @stage = nil
64
71
  @action = nil
65
- Card::DirectorRegister.delete self
72
+ end
73
+
74
+ def prepare_for_phases
75
+ @card.prepare_for_phases
76
+ @subdirectors.each(&:prepare_for_phases)
66
77
  end
67
78
 
68
79
  def validation_phase
69
- @running = true
70
80
  run_single_stage :initialize
71
81
  run_single_stage :prepare_to_validate
72
82
  run_single_stage :validate
@@ -124,13 +134,26 @@ class Card
124
134
  end
125
135
  end
126
136
 
137
+ def to_s
138
+ str = @card.name.to_s.clone
139
+ if @subdirectors
140
+ subs = subdirectors.map(&:card)
141
+ .map { |card| " #{card.name}" }.join "\n"
142
+ str << "\n#{subs}"
143
+ end
144
+ str
145
+ end
146
+
127
147
  private
128
148
 
129
149
  def run_single_stage stage, &block
130
150
  # puts "#{@card.name}: #{stage} stage".red
131
151
  @stage = stage_index stage
132
152
  return if @card.errors.any? && @stage <= stage_index(:validate)
133
-
153
+ if stage == :initialize
154
+ @running ||= true
155
+ prepare_for_phases
156
+ end
134
157
  # in the store stage it can be necessary that
135
158
  # other subcards must be saved before we save this card
136
159
  if stage == :store
@@ -227,5 +250,10 @@ class Card
227
250
  def initialize card, opts={}
228
251
  super card, opts, false
229
252
  end
253
+
254
+ def delete
255
+ @parent.subdirectors.delete self if @parent
256
+ super
257
+ end
230
258
  end
231
259
  end
data/lib/card/subcards.rb CHANGED
@@ -27,6 +27,9 @@ class Card
27
27
 
28
28
  def clear
29
29
  @keys.each do |key|
30
+ if (subcard = fetch_subcard key)
31
+ Card::DirectorRegister.delete subcard.director
32
+ end
30
33
  Card.cache.soft.delete key
31
34
  end
32
35
  @keys = ::Set.new
@@ -54,6 +57,10 @@ class Card
54
57
  key = absolutize_subcard_name(key).key unless @keys.include?(key)
55
58
  @keys.delete key
56
59
  removed_card = fetch_subcard key
60
+ if removed_card.current_action
61
+ removed_card.current_action.delete
62
+ end
63
+ Card::DirectorRegister.delete removed_card.director
57
64
  Card.cache.soft.delete key
58
65
  removed_card
59
66
  end
@@ -95,9 +102,10 @@ class Card
95
102
  end
96
103
  end
97
104
 
98
- def rename old_name, _new_name
105
+ def rename old_name, new_name
99
106
  return unless @keys.include? old_name.to_name.key
100
- # FIXME: something should happen here
107
+ @keys.delete old_name.to_name.key
108
+ @keys << new_name.to_name.key
101
109
  end
102
110
 
103
111
  def << value
@@ -223,7 +231,7 @@ class Card
223
231
  end
224
232
 
225
233
  def absolutize_subcard_name name
226
- if @context_card.name =~ /^\+/
234
+ if @context_card.name =~ /^\+/ || name.blank?
227
235
  name.to_name
228
236
  else
229
237
  name.to_name.to_absolute_name(@context_card.name)
@@ -14,6 +14,9 @@ class Card
14
14
  end
15
15
 
16
16
  def add card
17
+ if card.is_a? Card::StageDirector
18
+ card = card.card
19
+ end
17
20
  each do |dir|
18
21
  return dir if dir.card == card
19
22
  end
@@ -24,8 +27,18 @@ class Card
24
27
  dir
25
28
  end
26
29
 
30
+ alias_method :delete_director, :delete
31
+
27
32
  def delete card
28
- delete_if { |dir| dir.card == card }
33
+ if card.is_a? Card::StageDirector
34
+ delete_director card
35
+ else
36
+ delete_if { |dir| dir.card == card }
37
+ end
38
+ end
39
+
40
+ def add_director dir
41
+ add dir.card
29
42
  end
30
43
  end
31
44
  end
data/lib/cardio.rb CHANGED
@@ -92,14 +92,17 @@ module Cardio
92
92
  add_path 'db/migrate_deck_cards', root: root, with: 'db/migrate_cards'
93
93
  add_path 'db/seeds', with: 'db/seeds.rb'
94
94
 
95
- add_path 'config/initializers', glob: '**/*.rb'
95
+ add_path 'config/initializers', glob: '**/*.rb'
96
+ add_initializers root
96
97
  end
97
98
 
98
99
  def set_mod_paths
99
- each_mod_path do |mod_path|
100
- Dir.glob("#{mod_path}/*/initializers").each do |initializers_dir|
101
- paths['config/initializers'] << initializers_dir
102
- end
100
+ each_mod_path { |mod_path| add_initializers mod_path }
101
+ end
102
+
103
+ def add_initializers dir
104
+ Dir.glob("#{dir}/config/initializers").each do |initializers_dir|
105
+ paths['config/initializers'] << initializers_dir
103
106
  end
104
107
  end
105
108
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_dependency File.expand_path('../reference', __FILE__)
4
4
 
5
- module Card::Chunk
5
+ module Card::Content::Chunk
6
6
  class Include < Reference
7
7
  cattr_reader :options
8
8
  @@options = ::Set.new [
@@ -23,7 +23,7 @@ module Card::Chunk
23
23
  ]
24
24
  attr_reader :options
25
25
 
26
- Card::Chunk.register_class(
26
+ Card::Content::Chunk.register_class(
27
27
  self, prefix_re: '\\{\\{',
28
28
  full_re: /^\{\{([^\}]*)\}\}/,
29
29
  idx_char: '{')
@@ -2,11 +2,11 @@
2
2
 
3
3
  require_dependency File.expand_path('../reference', __FILE__)
4
4
 
5
- module Card::Chunk
5
+ module Card::Content::Chunk
6
6
  class Link < Reference
7
7
  attr_reader :link_text
8
8
  # Groups: $1, [$2]: [[$1]] or [[$1|$2]] or $3, $4: [$3][$4]
9
- Card::Chunk.register_class self,
9
+ Card::Content::Chunk.register_class self,
10
10
  prefix_re: '\\[',
11
11
  full_re: /^\[\[([^\]]+)\]\]/,
12
12
  idx_char: '['
@@ -78,7 +78,7 @@ module Card::Chunk
78
78
  replace_name_reference old_name, new_name
79
79
 
80
80
  if Card::Content === @link_text
81
- @link_text.find_chunks(Card::Chunk::Reference).each do |chunk|
81
+ @link_text.find_chunks(Card::Content::Chunk::Reference).each do |chunk|
82
82
  chunk.replace_reference old_name, new_name
83
83
  end
84
84
  elsif old_name.to_name == @link_text
@@ -1,21 +1,27 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- # These are basic chunks that have a pattern and can be protected.
4
- # They are used by rendering process to prevent wiki rendering
5
- # occuring within literal areas such as <code> and <pre> blocks
6
- # and within HTML tags.
7
- module Card::Chunk
8
- class EscapedLiteral < Abstract
9
- FULL_RE = { '[' => /^\\\[\[[^\]]*\]\]/, '{' => /^\\\{\{[^\}]*\}\}/ }.freeze
10
- Card::Chunk.register_class self, prefix_re: '\\\\(?:\\[\\[|\\{\\{)',
11
- idx_char: '\\'
3
+ class Card
4
+ class Content
5
+ module Chunk
6
+ # These are basic chunks that have a pattern and can be protected.
7
+ # They are used by rendering process to prevent wiki rendering
8
+ # occuring within literal areas such as <code> and <pre> blocks
9
+ # and within HTML tags.
10
+ class EscapedLiteral < Abstract
11
+ FULL_RE = { '[' => /^\\\[\[[^\]]*\]\]/,
12
+ '{' => /^\\\{\{[^\}]*\}\}/ }.freeze
13
+ Card::Content::Chunk.register_class self,
14
+ prefix_re: '\\\\(?:\\[\\[|\\{\\{)',
15
+ idx_char: '\\'
12
16
 
13
- def self.full_re prefix
14
- re = FULL_RE[prefix[1, 1]]
15
- end
17
+ def self.full_re prefix
18
+ FULL_RE[prefix[1, 1]]
19
+ end
16
20
 
17
- def interpret match, _content
18
- @process_chunk = match[0].sub(/^\\(.)/, '<span>\\1</span>')
21
+ def interpret match, _content
22
+ @process_chunk = match[0].sub(/^\\(.)/, '<span>\\1</span>')
23
+ end
24
+ end
19
25
  end
20
26
  end
21
27
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_dependency File.expand_path('../reference', __FILE__)
4
4
 
5
- module Card::Chunk
5
+ module Card::Content::Chunk
6
6
  # This should find +Alfred+ in expressions like
7
7
  # 1) {"name":"Alfred"}
8
8
  # 2a) {"name":["in","Alfred"]}
@@ -26,7 +26,7 @@ module Card::Chunk
26
26
  ).map(&:to_name)
27
27
  )
28
28
 
29
- Card::Chunk.register_class(
29
+ Card::Content::Chunk.register_class(
30
30
  self, prefix_re: '(?<=[:,\\[])\\s*"',
31
31
  # we check for colon, comma or square bracket before a quote
32
32
  # we have to use a lookbehind, otherwise
@@ -1,51 +1,60 @@
1
1
  # -*- encoding : utf-8 -*-
2
- module Card::Chunk
3
- class Reference < Abstract
4
- attr_accessor :referee_name, :name
2
+ class Card
3
+ class Content
4
+ module Chunk
5
+ class Reference < Abstract
6
+ attr_accessor :referee_name, :name
5
7
 
6
- def referee_name
7
- return if name.nil?
8
+ def referee_name
9
+ return if name.nil?
10
+ @referee_name ||=
11
+ begin
12
+ rendered_name = render_obj(name)
13
+ ref_card = fetch_referee_card rendered_name
14
+ ref_card ? ref_card.cardname : rendered_name.to_name
15
+ end
16
+ @referee_name = @referee_name.to_absolute(card.cardname).to_name
17
+ end
18
+
19
+ def referee_card
20
+ @referee_card ||= referee_name && Card.fetch(referee_name)
21
+ end
22
+
23
+ # FIXME: if we need this, then it should be faster, using fetch_id
24
+ # def referee_id
25
+ # referee_card and referee_card.id
26
+ # end
27
+
28
+ def replace_name_reference old_name, new_name
29
+ @referee_card = nil
30
+ @referee_name = nil
31
+ if name.is_a? Card::Content
32
+ name.find_chunks(Chunk::Reference).each do |chunk|
33
+ chunk.replace_reference old_name, new_name
34
+ end
35
+ else
36
+ @name = name.to_name.replace_part(old_name, new_name)
37
+ end
38
+ end
39
+
40
+ def render_obj raw
41
+ if format && raw.is_a?(Card::Content)
42
+ format.process_content raw
43
+ else
44
+ raw
45
+ end
46
+ end
8
47
 
9
- @referee_name ||= begin
10
- rendered_name = render_obj(name)
11
- ref_card =
48
+ private
49
+
50
+ def fetch_referee_card rendered_name
12
51
  case rendered_name # FIXME: this should be standard fetch option.
13
52
  when /^\~(\d+)$/ # get by id
14
53
  Card.fetch Regexp.last_match(1).to_i
15
54
  when /^\:(\w+)$/ # get by codename
16
55
  Card.fetch Regexp.last_match(1).to_sym
17
56
  end
18
- ref_card ? ref_card.cardname : rendered_name.to_name
19
- end
20
- @referee_name = @referee_name.to_absolute(card.cardname).to_name
21
- end
22
-
23
- def referee_card
24
- @referee_card ||= referee_name && Card.fetch(referee_name)
25
- end
26
-
27
- # FIXME: if we need this, then it should be faster, using fetch_id
28
- # def referee_id
29
- # referee_card and referee_card.id
30
- # end
31
-
32
- def replace_name_reference old_name, new_name
33
- @referee_card = nil
34
- @referee_name = nil
35
- if Card::Content === name
36
- name.find_chunks(Chunk::Reference).each do |chunk|
37
- chunk.replace_reference old_name, new_name
38
57
  end
39
- else
40
- @name = name.to_name.replace_part(old_name, new_name)
41
- end
42
- end
43
-
44
- def render_obj raw
45
- if format && Card::Content === raw
46
- format.process_content raw
47
- else
48
- raw
49
58
  end
50
59
  end
51
60
  end
@@ -16,7 +16,7 @@ require 'uri'
16
16
  # I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
17
17
  # The generic names are from www.bnoack.com/data/countrycode2.html)
18
18
  # [iso3166]: http://geotags.com/iso3166/
19
- module Card::Chunk
19
+ module Card::Content::Chunk
20
20
  class URI < Abstract
21
21
  SCHEMES = %w(irc http https ftp ssh git sftp file ldap ldaps mailto).freeze
22
22
 
@@ -25,9 +25,11 @@ module Card::Chunk
25
25
  attr_reader :uri, :link_text
26
26
  delegate :to, :scheme, :host, :port, :path, :query, :fragment, to: :uri
27
27
 
28
- Card::Chunk.register_class self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})(?:#{SCHEMES * '|'})\\:)",
29
- full_re: /^#{::URI.regexp(SCHEMES)}/,
30
- idx_char: ':'
28
+ Card::Content::Chunk.register_class(
29
+ self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})(?:#{SCHEMES * '|'})\\:)",
30
+ full_re: /^#{::URI.regexp(SCHEMES)}/,
31
+ idx_char: ':'
32
+ )
31
33
 
32
34
  class << self
33
35
  def full_match content, prefix
@@ -75,11 +77,12 @@ module Card::Chunk
75
77
  PREPEND_STR = 'mailto:'.freeze
76
78
  EMAIL = '[a-zA-Zd](?:[-a-zA-Zd]*[a-zA-Zd])?\\@'.freeze
77
79
 
78
- Card::Chunk.register_class self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{EMAIL})\\b",
79
- full_re: /^#{::URI.regexp(SCHEMES)}/,
80
- prepend_str: PREPEND_STR,
81
- idx_char: '@'
82
-
80
+ Card::Content::Chunk.register_class(
81
+ self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{EMAIL})\\b",
82
+ full_re: /^#{::URI.regexp(SCHEMES)}/,
83
+ prepend_str: PREPEND_STR,
84
+ idx_char: '@'
85
+ )
83
86
  def interpret match, content
84
87
  super
85
88
  @text = @text.sub(/^mailto:/, '') # this removes the prepended string from the unchanged match text
@@ -110,10 +113,11 @@ module Card::Chunk
110
113
  PREPEND_STR = 'http://'.freeze
111
114
  HOST = "(?:[a-zA-Z\d](?:[-a-zA-Z\d]*[a-zA-Z\d])?\\.)+#{TLDS}".freeze
112
115
 
113
- Card::Chunk.register_class self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{HOST})\\b",
114
- full_re: /^#{::URI.regexp(SCHEMES)}/,
115
- prepend_str: PREPEND_STR
116
-
116
+ Card::Content::Chunk.register_class(
117
+ self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{HOST})\\b",
118
+ full_re: /^#{::URI.regexp(SCHEMES)}/,
119
+ prepend_str: PREPEND_STR
120
+ )
117
121
  def interpret match, content
118
122
  super
119
123
  @text = @text.sub(/^http:\/\//, '') # this removes the prepended string from the unchanged match text