caracal_the_curve 1.4.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 (116) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +22 -0
  3. data/.github/workflows/publish_gem.yml +40 -0
  4. data/.gitignore +25 -0
  5. data/.travis.yml +20 -0
  6. data/CHANGELOG.md +141 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +842 -0
  10. data/Rakefile +7 -0
  11. data/caracal.gemspec +28 -0
  12. data/lib/caracal/core/bookmarks.rb +52 -0
  13. data/lib/caracal/core/custom_properties.rb +49 -0
  14. data/lib/caracal/core/file_name.rb +43 -0
  15. data/lib/caracal/core/fonts.rb +75 -0
  16. data/lib/caracal/core/iframes.rb +42 -0
  17. data/lib/caracal/core/ignorables.rb +47 -0
  18. data/lib/caracal/core/images.rb +37 -0
  19. data/lib/caracal/core/list_styles.rb +93 -0
  20. data/lib/caracal/core/lists.rb +57 -0
  21. data/lib/caracal/core/models/base_model.rb +51 -0
  22. data/lib/caracal/core/models/bookmark_model.rb +86 -0
  23. data/lib/caracal/core/models/border_model.rb +120 -0
  24. data/lib/caracal/core/models/custom_property_model.rb +60 -0
  25. data/lib/caracal/core/models/font_model.rb +64 -0
  26. data/lib/caracal/core/models/iframe_model.rb +148 -0
  27. data/lib/caracal/core/models/image_model.rb +133 -0
  28. data/lib/caracal/core/models/line_break_model.rb +15 -0
  29. data/lib/caracal/core/models/link_model.rb +94 -0
  30. data/lib/caracal/core/models/list_item_model.rb +108 -0
  31. data/lib/caracal/core/models/list_model.rb +132 -0
  32. data/lib/caracal/core/models/list_style_model.rb +118 -0
  33. data/lib/caracal/core/models/margin_model.rb +76 -0
  34. data/lib/caracal/core/models/namespace_model.rb +65 -0
  35. data/lib/caracal/core/models/page_break_model.rb +61 -0
  36. data/lib/caracal/core/models/page_number_model.rb +95 -0
  37. data/lib/caracal/core/models/page_size_model.rb +79 -0
  38. data/lib/caracal/core/models/paragraph_model.rb +186 -0
  39. data/lib/caracal/core/models/relationship_model.rb +114 -0
  40. data/lib/caracal/core/models/rule_model.rb +27 -0
  41. data/lib/caracal/core/models/style_model.rb +165 -0
  42. data/lib/caracal/core/models/table_cell_model.rb +176 -0
  43. data/lib/caracal/core/models/table_model.rb +206 -0
  44. data/lib/caracal/core/models/text_model.rb +118 -0
  45. data/lib/caracal/core/namespaces.rb +89 -0
  46. data/lib/caracal/core/page_breaks.rb +29 -0
  47. data/lib/caracal/core/page_numbers.rb +58 -0
  48. data/lib/caracal/core/page_settings.rb +74 -0
  49. data/lib/caracal/core/relationships.rb +90 -0
  50. data/lib/caracal/core/rules.rb +35 -0
  51. data/lib/caracal/core/styles.rb +86 -0
  52. data/lib/caracal/core/tables.rb +42 -0
  53. data/lib/caracal/core/text.rb +75 -0
  54. data/lib/caracal/document.rb +272 -0
  55. data/lib/caracal/errors.rb +23 -0
  56. data/lib/caracal/renderers/app_renderer.rb +41 -0
  57. data/lib/caracal/renderers/content_types_renderer.rb +54 -0
  58. data/lib/caracal/renderers/core_renderer.rb +44 -0
  59. data/lib/caracal/renderers/custom_renderer.rb +64 -0
  60. data/lib/caracal/renderers/document_renderer.rb +427 -0
  61. data/lib/caracal/renderers/fonts_renderer.rb +56 -0
  62. data/lib/caracal/renderers/footer_renderer.rb +90 -0
  63. data/lib/caracal/renderers/numbering_renderer.rb +88 -0
  64. data/lib/caracal/renderers/package_relationships_renderer.rb +51 -0
  65. data/lib/caracal/renderers/relationships_renderer.rb +48 -0
  66. data/lib/caracal/renderers/settings_renderer.rb +58 -0
  67. data/lib/caracal/renderers/styles_renderer.rb +181 -0
  68. data/lib/caracal/renderers/xml_renderer.rb +83 -0
  69. data/lib/caracal/utilities.rb +23 -0
  70. data/lib/caracal/version.rb +3 -0
  71. data/lib/caracal.rb +40 -0
  72. data/lib/tilt/caracal.rb +21 -0
  73. data/spec/lib/caracal/core/bookmarks_spec.rb +35 -0
  74. data/spec/lib/caracal/core/file_name_spec.rb +54 -0
  75. data/spec/lib/caracal/core/fonts_spec.rb +119 -0
  76. data/spec/lib/caracal/core/iframes_spec.rb +29 -0
  77. data/spec/lib/caracal/core/ignorables_spec.rb +79 -0
  78. data/spec/lib/caracal/core/images_spec.rb +25 -0
  79. data/spec/lib/caracal/core/list_styles_spec.rb +121 -0
  80. data/spec/lib/caracal/core/lists_spec.rb +43 -0
  81. data/spec/lib/caracal/core/models/base_model_spec.rb +38 -0
  82. data/spec/lib/caracal/core/models/bookmark_model_spec.rb +135 -0
  83. data/spec/lib/caracal/core/models/border_model_spec.rb +159 -0
  84. data/spec/lib/caracal/core/models/font_model_spec.rb +92 -0
  85. data/spec/lib/caracal/core/models/iframe_model_spec.rb +83 -0
  86. data/spec/lib/caracal/core/models/image_model_spec.rb +225 -0
  87. data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
  88. data/spec/lib/caracal/core/models/link_model_spec.rb +179 -0
  89. data/spec/lib/caracal/core/models/list_item_model_spec.rb +197 -0
  90. data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
  91. data/spec/lib/caracal/core/models/list_style_model_spec.rb +198 -0
  92. data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
  93. data/spec/lib/caracal/core/models/namespace_model_spec.rb +107 -0
  94. data/spec/lib/caracal/core/models/page_break_model_spec.rb +21 -0
  95. data/spec/lib/caracal/core/models/page_number_model_spec.rb +136 -0
  96. data/spec/lib/caracal/core/models/page_size_model_spec.rb +101 -0
  97. data/spec/lib/caracal/core/models/paragraph_model_spec.rb +196 -0
  98. data/spec/lib/caracal/core/models/relationship_model_spec.rb +193 -0
  99. data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
  100. data/spec/lib/caracal/core/models/style_model_spec.rb +225 -0
  101. data/spec/lib/caracal/core/models/table_cell_model_spec.rb +230 -0
  102. data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
  103. data/spec/lib/caracal/core/models/text_model_spec.rb +154 -0
  104. data/spec/lib/caracal/core/namespaces_spec.rb +116 -0
  105. data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
  106. data/spec/lib/caracal/core/page_numbers_spec.rb +89 -0
  107. data/spec/lib/caracal/core/page_settings_spec.rb +151 -0
  108. data/spec/lib/caracal/core/relationships_spec.rb +119 -0
  109. data/spec/lib/caracal/core/rules_spec.rb +25 -0
  110. data/spec/lib/caracal/core/styles_spec.rb +129 -0
  111. data/spec/lib/caracal/core/tables_spec.rb +25 -0
  112. data/spec/lib/caracal/core/text_spec.rb +52 -0
  113. data/spec/lib/caracal/errors_spec.rb +10 -0
  114. data/spec/spec_helper.rb +8 -0
  115. data/spec/support/_fixtures/snippet.docx +0 -0
  116. metadata +292 -0
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
data/caracal.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'caracal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'caracal_the_curve'
8
+ spec.version = Caracal::VERSION
9
+ spec.authors = ['Trade Infomatics', 'John Dugan']
10
+ spec.email = ['jpdugan@gmail.com']
11
+ spec.summary = %q{ Fast, professional Microsoft Word (docx) writer for Ruby. }
12
+ spec.description = %q{ Caracal is a pure Ruby Microsoft Word generation library that produces professional quality MSWord documents (docx) using a simple, HTML-style DSL. }
13
+ spec.homepage = 'https://github.com/trade-informatics/caracal'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'nokogiri', '~> 1.6'
22
+ spec.add_dependency 'rubyzip', ['>= 1.1.0', '< 3.0']
23
+ spec.add_dependency 'tilt', '>= 1.4'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 2.4'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ end
@@ -0,0 +1,52 @@
1
+ require 'caracal/core/models/bookmark_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to adding
9
+ # bookmarks to the document.
10
+ #
11
+ module Bookmarks
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #------------------------------------------------
16
+ # Public Methods
17
+ #------------------------------------------------
18
+
19
+ #========== BOOKMARKS ===========================
20
+
21
+ def bookmark_start(*args, &block)
22
+ options = Caracal::Utilities.extract_options!(args)
23
+ options.merge!({ start: true})
24
+
25
+ model = Caracal::Core::Models::BookmarkModel.new(options, &block)
26
+ if model.valid?
27
+ contents << model
28
+ else
29
+ raise Caracal::Errors::InvalidModelError, 'Bookmark starting tags require an id and a name.'
30
+ end
31
+ model
32
+ end
33
+
34
+ def bookmark_end(*args, &block)
35
+ options = Caracal::Utilities.extract_options!(args)
36
+ options.merge!({ start: false})
37
+
38
+ model = Caracal::Core::Models::BookmarkModel.new(options, &block)
39
+ if model.valid?
40
+ contents << model
41
+ else
42
+ raise Caracal::Errors::InvalidModelError, 'Bookmark ending tags require an id.'
43
+ end
44
+ model
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,49 @@
1
+ require 'caracal/core/models/custom_property_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to setting the
9
+ # document's custom properties.
10
+ #
11
+ module CustomProperties
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Public Methods
17
+ #-------------------------------------------------------------
18
+
19
+ # This method controls the custom properties.
20
+ #
21
+ def custom_property(options={}, &block)
22
+ model = Caracal::Core::Models::CustomPropertyModel.new(options, &block)
23
+ if model.valid?
24
+ register_property(model)
25
+ end
26
+ model
27
+ end
28
+
29
+
30
+ #============== GETTERS =============================
31
+
32
+ def custom_props
33
+ @custom_props ||= []
34
+ end
35
+
36
+
37
+ #============== REGISTRATION ========================
38
+
39
+ def register_property(model)
40
+ custom_props << model
41
+ model
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,43 @@
1
+ module Caracal
2
+ module Core
3
+
4
+ # This module encapsulates all the functionality related to setting the
5
+ # document's name.
6
+ #
7
+ module FileName
8
+ def self.included(base)
9
+ base.class_eval do
10
+
11
+ #-------------------------------------------------------------
12
+ # Configuration
13
+ #-------------------------------------------------------------
14
+
15
+ # constants
16
+ const_set(:DEFAULT_FILE_NAME, 'caracal.docx')
17
+
18
+ # accessors
19
+ attr_reader :name
20
+ attr_reader :path
21
+
22
+
23
+ #-------------------------------------------------------------
24
+ # Public Methods
25
+ #-------------------------------------------------------------
26
+
27
+ # This method sets the name of the output file. Defaults
28
+ # to the name of the library.
29
+ #
30
+ def file_name(value=nil)
31
+ v = value.to_s.strip
32
+ a = v.split('/')
33
+
34
+ @name = (v == '') ? self.class::DEFAULT_FILE_NAME : a.last
35
+ @path = (a.size > 1) ? v : "./#{ v }"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,75 @@
1
+ require 'caracal/core/models/font_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to registering
9
+ # fonts.
10
+ #
11
+ module Fonts
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Class Methods
17
+ #-------------------------------------------------------------
18
+
19
+ def self.default_fonts
20
+ [
21
+ { name: 'Arial' },
22
+ { name: 'Trebuchet MS' }
23
+ ]
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Public Methods
29
+ #-------------------------------------------------------------
30
+
31
+ #============== ATTRIBUTES ==========================
32
+
33
+ def font(options={}, &block)
34
+ model = Caracal::Core::Models::FontModel.new(options, &block)
35
+
36
+ if model.valid?
37
+ register_font(model)
38
+ else
39
+ raise Caracal::Errors::InvalidModelError, 'font must specify the :name attribute.'
40
+ end
41
+ model
42
+ end
43
+
44
+
45
+ #============== GETTERS =============================
46
+
47
+ def fonts
48
+ @fonts ||= []
49
+ end
50
+
51
+ def find_font(name)
52
+ fonts.find { |f| f.matches?(name) }
53
+ end
54
+
55
+
56
+ #============== REGISTRATION ========================
57
+
58
+ def register_font(model)
59
+ unregister_font(model.font_name)
60
+ fonts << model
61
+ model
62
+ end
63
+
64
+ def unregister_font(name)
65
+ if f = find_font(name)
66
+ fonts.delete(f)
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,42 @@
1
+ require 'caracal/core/models/iframe_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to inserting
9
+ # word document snippets into the document.
10
+ #
11
+ module IFrames
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Public Methods
17
+ #-------------------------------------------------------------
18
+
19
+ def iframe(options={}, &block)
20
+ model = Caracal::Core::Models::IFrameModel.new(options, &block)
21
+ if model.valid?
22
+ model.preprocess!
23
+ model.namespaces.each do |(prefix, href)|
24
+ namespace({ prefix: prefix, href: href })
25
+ end
26
+ model.ignorables.each do |prefix|
27
+ ignorable(prefix)
28
+ end
29
+
30
+ contents << model
31
+ else
32
+ raise Caracal::Errors::InvalidModelError, 'IFrameModel requires either the :url or :data argument.'
33
+ end
34
+ model
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module Caracal
2
+ module Core
3
+
4
+ # This module encapsulates all the functionality related to registering and
5
+ # retrieving ignorable namespaces.
6
+ #
7
+ module Ignorables
8
+ def self.included(base)
9
+ base.class_eval do
10
+
11
+ #-------------------------------------------------------------
12
+ # Public Methods
13
+ #-------------------------------------------------------------
14
+
15
+ #============== ATTRIBUTES ==========================
16
+
17
+ def ignorable(prefix)
18
+ register_ignorable(prefix)
19
+ end
20
+
21
+
22
+ #============== GETTERS =============================
23
+
24
+ def ignorables
25
+ @ignorables ||= []
26
+ end
27
+
28
+
29
+ #============== REGISTRATION ========================
30
+
31
+ def register_ignorable(prefix)
32
+ unless ignorables.include?(prefix)
33
+ ignorables << prefix
34
+ prefix
35
+ end
36
+ end
37
+
38
+ def unregister_ignorable(prefix)
39
+ ignorables.delete(prefix)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ require 'caracal/core/models/image_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to adding
9
+ # images to the document.
10
+ #
11
+ module Images
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Public Methods
17
+ #-------------------------------------------------------------
18
+
19
+ def img(*args, &block)
20
+ options = Caracal::Utilities.extract_options!(args)
21
+ options.merge!({ url: args.first }) if args.first
22
+
23
+ model = Caracal::Core::Models::ImageModel.new(options, &block)
24
+ if model.valid?
25
+ contents << model
26
+ else
27
+ raise Caracal::Errors::InvalidModelError, 'Images require an URL and positive size/margin values.'
28
+ end
29
+ model
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ require 'caracal/core/models/list_style_model'
3
+ require 'caracal/errors'
4
+
5
+
6
+ module Caracal
7
+ module Core
8
+
9
+ # This module encapsulates all the functionality related to defining
10
+ # list styles.
11
+ #
12
+ module ListStyles
13
+ def self.included(base)
14
+ base.class_eval do
15
+
16
+ #-------------------------------------------------------------
17
+ # Class Methods
18
+ #-------------------------------------------------------------
19
+
20
+ def self.default_list_styles
21
+ [
22
+ { type: :ordered, level: 0, format: 'decimal', value: '%1.', left: 720, indent: 360 },
23
+ { type: :ordered, level: 1, format: 'lowerLetter', value: '%2.', left: 1440, indent: 1080 },
24
+ { type: :ordered, level: 2, format: 'lowerRoman', value: '%3.', left: 2160, indent: 1800, align: :right },
25
+ { type: :ordered, level: 3, format: 'decimal', value: '%4.', left: 2880, indent: 2520 },
26
+ { type: :ordered, level: 4, format: 'lowerLetter', value: '%5.', left: 3600, indent: 3240 },
27
+ { type: :ordered, level: 5, format: 'lowerRoman', value: '%6.', left: 4320, indent: 3960, align: :right },
28
+ { type: :ordered, level: 6, format: 'decimal', value: '%7.', left: 5040, indent: 4680 },
29
+ { type: :ordered, level: 7, format: 'lowerLetter', value: '%8.', left: 5760, indent: 5400 },
30
+ { type: :ordered, level: 8, format: 'lowerRoman', value: '%9.', left: 6480, indent: 6120, align: :right },
31
+
32
+ { type: :unordered, level: 0, format: 'bullet', value: '●', left: 720, indent: 360 },
33
+ { type: :unordered, level: 1, format: 'bullet', value: '○', left: 1440, indent: 1080 },
34
+ { type: :unordered, level: 2, format: 'bullet', value: '■', left: 2160, indent: 1800 },
35
+ { type: :unordered, level: 3, format: 'bullet', value: '●', left: 2880, indent: 2520 },
36
+ { type: :unordered, level: 4, format: 'bullet', value: '○', left: 3600, indent: 3240 },
37
+ { type: :unordered, level: 5, format: 'bullet', value: '■', left: 4320, indent: 3960 },
38
+ { type: :unordered, level: 6, format: 'bullet', value: '●', left: 5040, indent: 4680 },
39
+ { type: :unordered, level: 7, format: 'bullet', value: '○', left: 5760, indent: 5400 },
40
+ { type: :unordered, level: 8, format: 'bullet', value: '■', left: 6480, indent: 6120 }
41
+ ]
42
+ end
43
+
44
+
45
+ #-------------------------------------------------------------
46
+ # Public Methods
47
+ #-------------------------------------------------------------
48
+
49
+ #============== ATTRIBUTES ==========================
50
+
51
+ def list_style(options={}, &block)
52
+ model = Caracal::Core::Models::ListStyleModel.new(options, &block)
53
+
54
+ if model.valid?
55
+ register_list_style(model)
56
+ else
57
+ raise Caracal::Errors::InvalidModelError, 'list style must define a :type, :level, :format, and :value.'
58
+ end
59
+ model
60
+ end
61
+
62
+
63
+ #============== GETTERS =============================
64
+
65
+ def list_styles
66
+ @list_styles ||= []
67
+ end
68
+
69
+ def find_list_style(type, level)
70
+ list_styles.find { |s| s.matches?(type, level) }
71
+ end
72
+
73
+
74
+ #============== REGISTRATION ========================
75
+
76
+ def register_list_style(model)
77
+ unregister_list_style(model.style_type, model.style_level)
78
+ list_styles << model
79
+ model
80
+ end
81
+
82
+ def unregister_list_style(type, level)
83
+ if s = find_list_style(type, level)
84
+ list_styles.delete(s)
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,57 @@
1
+ require 'caracal/core/models/list_model'
2
+ require 'caracal/errors'
3
+
4
+
5
+ module Caracal
6
+ module Core
7
+
8
+ # This module encapsulates all the functionality related to adding
9
+ # horizontal rules to the document.
10
+ #
11
+ module Lists
12
+ def self.included(base)
13
+ base.class_eval do
14
+
15
+ #-------------------------------------------------------------
16
+ # Public Methods
17
+ #-------------------------------------------------------------
18
+
19
+ #============== ATTRIBUTES ==========================
20
+
21
+ def ol(options={}, &block)
22
+ options.merge!({ type: :ordered, level: 0 })
23
+
24
+ model = Caracal::Core::Models::ListModel.new(options, &block)
25
+ if model.valid?
26
+ contents << model
27
+ else
28
+ raise Caracal::Errors::InvalidModelError, 'Ordered lists require at least one list item.'
29
+ end
30
+ model
31
+ end
32
+
33
+ def ul(options={}, &block)
34
+ options.merge!({ type: :unordered, level: 0 })
35
+
36
+ model = Caracal::Core::Models::ListModel.new(options, &block)
37
+ if model.valid?
38
+ contents << model
39
+ else
40
+ raise Caracal::Errors::InvalidModelError, 'Unordered lists require at least one list item.'
41
+ end
42
+ model
43
+ end
44
+
45
+
46
+ #============== GETTERS ==========================
47
+
48
+ def toplevel_lists
49
+ @toplevel_lists ||= []
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,51 @@
1
+ module Caracal
2
+ module Core
3
+ module Models
4
+
5
+ # This class encapsulates the logic needed for functions that
6
+ # do not store or manipulate data.
7
+ #
8
+ class BaseModel
9
+
10
+ #-------------------------------------------------------------
11
+ # Configuration
12
+ #-------------------------------------------------------------
13
+
14
+ # initialization
15
+ def initialize(options={}, &block)
16
+ options.keep_if { |k,v| option_keys.include? k }
17
+ options.each do |(key, value)|
18
+ send(key, value)
19
+ end
20
+
21
+ if block_given?
22
+ (block.arity < 1) ? instance_eval(&block) : block[self]
23
+ end
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Public Instance Methods
29
+ #-------------------------------------------------------------
30
+
31
+ #=============== VALIDATION ===========================
32
+
33
+ def valid?
34
+ true
35
+ end
36
+
37
+
38
+ #-------------------------------------------------------------
39
+ # Private Instance Methods
40
+ #-------------------------------------------------------------
41
+ private
42
+
43
+ def option_keys
44
+ []
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,86 @@
1
+ require 'caracal/core/models/base_model'
2
+
3
+
4
+ module Caracal
5
+ module Core
6
+ module Models
7
+
8
+ # This class encapsulates the logic needed to store and manipulate
9
+ # bookmarks.
10
+ #
11
+ class BookmarkModel < BaseModel
12
+
13
+ #--------------------------------------------------
14
+ # Configuration
15
+ #--------------------------------------------------
16
+
17
+ # accessors
18
+ attr_reader :bookmark_start
19
+ attr_reader :bookmark_id
20
+ attr_reader :bookmark_name
21
+
22
+
23
+ #--------------------------------------------------
24
+ # Public Methods
25
+ #--------------------------------------------------
26
+
27
+ #========== GETTERS ===============================
28
+
29
+ # .run_attributes
30
+ def run_attributes
31
+ {
32
+ start: bookmark_start,
33
+ id: bookmark_id,
34
+ name: bookmark_name
35
+ }
36
+ end
37
+
38
+
39
+ #========== SETTERS ===============================
40
+
41
+ # booleans
42
+ [:start].each do |m|
43
+ define_method "#{ m }" do |value|
44
+ instance_variable_set("@bookmark_#{ m }", !!value)
45
+ end
46
+ end
47
+
48
+ # strings
49
+ [:id, :name].each do |m|
50
+ define_method "#{ m }" do |value|
51
+ instance_variable_set("@bookmark_#{ m }", value.to_s)
52
+ end
53
+ end
54
+
55
+
56
+ #========== STATE HELPERS =========================
57
+
58
+ def start?
59
+ !!bookmark_start
60
+ end
61
+
62
+
63
+ #========== VALIDATION ============================
64
+
65
+ def valid?
66
+ a = [:id]
67
+ a << :name if start?
68
+
69
+ a.map { |m| send("bookmark_#{ m }") }.compact.size == a.size
70
+ end
71
+
72
+
73
+ #--------------------------------------------------
74
+ # Private Methods
75
+ #--------------------------------------------------
76
+ private
77
+
78
+ def option_keys
79
+ [:id, :name, :start]
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end