active_canvas 0.0.5 → 0.1.0

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -1
  3. data/app/assets/javascripts/active_canvas/admin/data_panel.js +357 -0
  4. data/app/assets/javascripts/active_canvas/admin/field_builder.js +84 -0
  5. data/app/assets/javascripts/active_canvas/admin/media_select_preview.js +11 -0
  6. data/app/assets/javascripts/active_canvas/editor/ac_bindings.js +81 -0
  7. data/app/assets/javascripts/active_canvas/editor/ac_chips.js +192 -0
  8. data/app/assets/javascripts/active_canvas/editor/code_panel.js +10 -7
  9. data/app/assets/javascripts/active_canvas/editor/directive_traits.js +95 -0
  10. data/app/assets/javascripts/active_canvas/editor/live_data.js +178 -0
  11. data/app/assets/javascripts/active_canvas/editor/panels.js +23 -7
  12. data/app/assets/javascripts/active_canvas/editor/preview_modal.js +112 -0
  13. data/app/assets/javascripts/active_canvas/editor/template_validator.js +95 -0
  14. data/app/assets/javascripts/active_canvas/editor.js +21 -3
  15. data/app/assets/stylesheets/active_canvas/editor.css +626 -0
  16. data/app/controllers/active_canvas/admin/application_controller.rb +8 -0
  17. data/app/controllers/active_canvas/admin/collection_items_controller.rb +93 -0
  18. data/app/controllers/active_canvas/admin/collections_controller.rb +51 -0
  19. data/app/controllers/active_canvas/admin/form_submissions_controller.rb +51 -0
  20. data/app/controllers/active_canvas/admin/pages_controller.rb +127 -5
  21. data/app/controllers/active_canvas/form_submissions_controller.rb +90 -0
  22. data/app/controllers/active_canvas/pages_controller.rb +8 -0
  23. data/app/controllers/active_canvas/redirects_controller.rb +10 -0
  24. data/app/helpers/active_canvas/admin/collection_items_helper.rb +33 -0
  25. data/app/models/active_canvas/auto_drop.rb +69 -0
  26. data/app/models/active_canvas/collection.rb +98 -0
  27. data/app/models/active_canvas/collection_item.rb +66 -0
  28. data/app/models/active_canvas/collection_item_version.rb +18 -0
  29. data/app/models/active_canvas/current.rb +2 -0
  30. data/app/models/active_canvas/form_submission.rb +9 -0
  31. data/app/models/active_canvas/page.rb +76 -15
  32. data/app/models/active_canvas/page_redirect.rb +7 -0
  33. data/app/services/active_canvas/collection_schema.rb +110 -0
  34. data/app/services/active_canvas/collection_source.rb +81 -0
  35. data/app/services/active_canvas/content_sanitizer.rb +33 -21
  36. data/app/services/active_canvas/form_schema.rb +48 -0
  37. data/app/services/active_canvas/form_stamper.rb +86 -0
  38. data/app/services/active_canvas/template_renderer/binding_resolver.rb +138 -0
  39. data/app/services/active_canvas/template_renderer/directive_expander.rb +54 -0
  40. data/app/services/active_canvas/template_renderer.rb +160 -0
  41. data/app/views/active_canvas/admin/collection_items/_field_input.html.erb +40 -0
  42. data/app/views/active_canvas/admin/collection_items/_form.html.erb +28 -0
  43. data/app/views/active_canvas/admin/collection_items/edit.html.erb +24 -0
  44. data/app/views/active_canvas/admin/collection_items/history.html.erb +34 -0
  45. data/app/views/active_canvas/admin/collection_items/index.html.erb +63 -0
  46. data/app/views/active_canvas/admin/collection_items/new.html.erb +9 -0
  47. data/app/views/active_canvas/admin/collections/_field_builder.html.erb +35 -0
  48. data/app/views/active_canvas/admin/collections/_form.html.erb +31 -0
  49. data/app/views/active_canvas/admin/collections/edit.html.erb +10 -0
  50. data/app/views/active_canvas/admin/collections/index.html.erb +45 -0
  51. data/app/views/active_canvas/admin/collections/new.html.erb +9 -0
  52. data/app/views/active_canvas/admin/form_submissions/index.html.erb +80 -0
  53. data/app/views/active_canvas/admin/form_submissions/show.html.erb +99 -0
  54. data/app/views/active_canvas/admin/pages/_data_panel.html.erb +81 -0
  55. data/app/views/active_canvas/admin/pages/_form.html.erb +10 -0
  56. data/app/views/active_canvas/admin/pages/editor.html.erb +62 -1
  57. data/app/views/active_canvas/pages/show.html.erb +4 -1
  58. data/app/views/layouts/active_canvas/admin/application.html.erb +15 -0
  59. data/config/routes.rb +20 -0
  60. data/db/migrate/20260517100001_add_template_enabled_and_bindings_to_active_canvas_pages.rb +6 -0
  61. data/db/migrate/20260517100002_add_bindings_to_active_canvas_page_versions.rb +6 -0
  62. data/db/migrate/20260702000001_create_active_canvas_page_redirects.rb +11 -0
  63. data/db/migrate/20260702000002_create_active_canvas_form_submissions.rb +14 -0
  64. data/db/migrate/20260702000003_create_active_canvas_collections.rb +12 -0
  65. data/db/migrate/20260702000004_create_active_canvas_collection_items.rb +16 -0
  66. data/db/migrate/20260702000005_create_active_canvas_collection_item_versions.rb +17 -0
  67. data/lib/active_canvas/configuration.rb +32 -1
  68. data/lib/active_canvas/data_sources/errors.rb +51 -0
  69. data/lib/active_canvas/data_sources/param_spec.rb +64 -0
  70. data/lib/active_canvas/data_sources/registration.rb +60 -0
  71. data/lib/active_canvas/data_sources/source.rb +47 -0
  72. data/lib/active_canvas/data_sources.rb +54 -0
  73. data/lib/active_canvas/engine.rb +15 -0
  74. data/lib/active_canvas/version.rb +1 -1
  75. data/lib/active_canvas.rb +6 -0
  76. metadata +85 -3
@@ -106,6 +106,26 @@ module ActiveCanvas
106
106
  # Allowed hosts for AI-generated image downloads
107
107
  attr_accessor :allowed_ai_image_hosts
108
108
 
109
+ # ==> Dynamic Content (Liquid templating)
110
+ # Maximum total output size in bytes
111
+ attr_accessor :template_render_length_limit
112
+ # Maximum render score (Liquid's complexity counter)
113
+ attr_accessor :template_render_score_limit
114
+ # Maximum assign score (Liquid variable-assignment counter)
115
+ attr_accessor :template_assign_score_limit
116
+ # Default on_error for data sources: :raise or :silent
117
+ attr_accessor :template_default_on_error
118
+
119
+ # ==> Forms
120
+ # Host hook called with each stored FormSubmission
121
+ attr_accessor :on_form_submission
122
+
123
+ # Reject submissions arriving faster than this many seconds after render
124
+ attr_accessor :form_min_submit_seconds
125
+
126
+ # Per-IP submissions allowed per minute
127
+ attr_accessor :form_rate_limit_per_minute
128
+
109
129
  # Dangerous content types that are always blocked
110
130
  DANGEROUS_CONTENT_TYPES = %w[
111
131
  application/x-executable
@@ -170,7 +190,7 @@ module ActiveCanvas
170
190
  @allowed_html_attributes = %w[
171
191
  class id style href src alt title target rel
172
192
  width height loading name type value placeholder
173
- disabled readonly checked selected multiple
193
+ disabled readonly checked selected multiple required
174
194
  action method enctype
175
195
  controls autoplay loop muted poster
176
196
  frameborder allowfullscreen allow
@@ -186,6 +206,17 @@ module ActiveCanvas
186
206
  oaidalleapiprodscus.blob.core.windows.net
187
207
  dalleprodsec.blob.core.windows.net
188
208
  ]
209
+
210
+ # Dynamic Content (Liquid templating)
211
+ @template_render_length_limit = 1_000_000
212
+ @template_render_score_limit = 100_000
213
+ @template_assign_score_limit = 10_000
214
+ @template_default_on_error = :raise
215
+
216
+ # Forms
217
+ @on_form_submission = nil
218
+ @form_min_submit_seconds = 3
219
+ @form_rate_limit_per_minute = 5
189
220
  end
190
221
 
191
222
  # Get effective allowed content types (includes SVG if enabled, excludes dangerous types)
@@ -0,0 +1,51 @@
1
+ module ActiveCanvas
2
+ module DataSources
3
+ class Error < StandardError; end
4
+
5
+ class UnknownSource < Error
6
+ def initialize(name)
7
+ super("Unknown data source: #{name.inspect}")
8
+ @name = name
9
+ end
10
+ attr_reader :name
11
+ end
12
+
13
+ class InvalidParam < Error
14
+ def initialize(source_name, param_name, reason)
15
+ super("Data source #{source_name.inspect} param #{param_name.inspect}: #{reason}")
16
+ @source_name = source_name
17
+ @param_name = param_name
18
+ end
19
+ attr_reader :source_name, :param_name
20
+ end
21
+
22
+ class UnsafeData < Error
23
+ def initialize(source_name, object_class)
24
+ super(
25
+ "Data source #{source_name.inspect} returned a #{object_class} object without a Drop wrapper. " \
26
+ "Wrap results with auto_drop or a custom Liquid::Drop subclass."
27
+ )
28
+ @source_name = source_name
29
+ @object_class = object_class
30
+ end
31
+ attr_reader :source_name, :object_class
32
+ end
33
+
34
+ class RegistryFrozen < Error
35
+ def initialize(name)
36
+ super("Cannot register data source #{name.inspect} after boot. Move the registration into config/initializers/active_canvas.rb.")
37
+ end
38
+ end
39
+
40
+ class TemplateRenderError < StandardError
41
+ attr_reader :line, :column, :original
42
+
43
+ def initialize(message, line: nil, column: nil, original: nil)
44
+ super(message)
45
+ @line = line
46
+ @column = column
47
+ @original = original
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,64 @@
1
+ module ActiveCanvas
2
+ module DataSources
3
+ class ParamSpec
4
+ ALLOWED_TYPES = %i[integer string boolean].freeze
5
+
6
+ attr_reader :name, :type, :default, :range, :allowed, :source_name
7
+
8
+ def initialize(name, source_name:, type:, default: nil, range: nil, allowed: nil)
9
+ unless ALLOWED_TYPES.include?(type)
10
+ raise ArgumentError, "Param #{name.inspect} type must be one of #{ALLOWED_TYPES.inspect}, got #{type.inspect}"
11
+ end
12
+ @name = name.to_sym
13
+ @source_name = source_name
14
+ @type = type
15
+ @default = default
16
+ @range = range
17
+ @allowed = allowed
18
+ end
19
+
20
+ def resolve(params_hash)
21
+ value = params_hash.key?(name) ? params_hash[name] : (params_hash.key?(name.to_s) ? params_hash[name.to_s] : nil)
22
+ coerce(value)
23
+ end
24
+
25
+ def coerce(value)
26
+ return default if value.nil?
27
+
28
+ coerced = case type
29
+ when :integer then coerce_integer(value)
30
+ when :string then value.to_s
31
+ when :boolean then coerce_boolean(value)
32
+ end
33
+
34
+ validate!(coerced) unless coerced.nil?
35
+ coerced
36
+ end
37
+
38
+ private
39
+
40
+ def coerce_integer(value)
41
+ Integer(value)
42
+ rescue ArgumentError, TypeError
43
+ invalid!("not a valid integer: #{value.inspect}")
44
+ end
45
+
46
+ def coerce_boolean(value)
47
+ case value
48
+ when true, "true", 1, "1" then true
49
+ when false, "false", 0, "0" then false
50
+ else invalid!("not a valid boolean: #{value.inspect}")
51
+ end
52
+ end
53
+
54
+ def validate!(value)
55
+ invalid!("#{value.inspect} not in range #{range}") if range && !range.include?(value)
56
+ invalid!("#{value.inspect} not in allowed values #{allowed.inspect}") if allowed && !allowed.include?(value)
57
+ end
58
+
59
+ def invalid!(reason)
60
+ raise InvalidParam.new(source_name, name, reason)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,60 @@
1
+ module ActiveCanvas
2
+ module DataSources
3
+ # DSL builder used inside DataSources.register blocks.
4
+ class Registration
5
+ def initialize(name)
6
+ @name = name
7
+ @params = {}
8
+ @fetch_block = nil
9
+ @drop_class = nil
10
+ @auto_drop_config = nil
11
+ @on_error = nil
12
+ @returns = :list
13
+ end
14
+
15
+ def param(name, type:, default: nil, range: nil, allowed: nil)
16
+ @params[name.to_sym] = ParamSpec.new(
17
+ name, source_name: @name, type: type, default: default, range: range, allowed: allowed
18
+ )
19
+ end
20
+
21
+ def fetch(&block)
22
+ @fetch_block = block
23
+ end
24
+
25
+ def drop(klass)
26
+ @drop_class = klass
27
+ end
28
+
29
+ def auto_drop(attributes:, associations: {}, html: [])
30
+ @auto_drop_config = { attributes: attributes, associations: associations, html: html }
31
+ end
32
+
33
+ def on_error(mode)
34
+ unless %i[raise silent].include?(mode)
35
+ raise ArgumentError, "on_error must be :raise or :silent, got #{mode.inspect}"
36
+ end
37
+ @on_error = mode
38
+ end
39
+
40
+ # Whether the fetch block returns a list (loopable) or a single value.
41
+ def returns(shape)
42
+ raise ArgumentError, "returns must be :one or :list, got #{shape.inspect}" unless %i[one list].include?(shape)
43
+ @returns = shape
44
+ end
45
+
46
+ def to_source
47
+ raise ArgumentError, "fetch block required for data source #{@name.inspect}" unless @fetch_block
48
+ Source.new(
49
+ name: @name,
50
+ params: @params,
51
+ fetch_block: @fetch_block,
52
+ drop_class: @drop_class,
53
+ auto_drop_config: @auto_drop_config,
54
+ on_error: @on_error || ActiveCanvas.config.template_default_on_error,
55
+ returns: @returns
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ module ActiveCanvas
2
+ module DataSources
3
+ class Source
4
+ attr_reader :name, :params, :drop_class, :auto_drop_config, :on_error
5
+
6
+ def initialize(name:, params:, fetch_block:, drop_class:, auto_drop_config:, on_error:, returns: :list)
7
+ @name = name
8
+ @params = params
9
+ @fetch_block = fetch_block
10
+ @drop_class = drop_class
11
+ @auto_drop_config = auto_drop_config || { attributes: [], associations: {}, html: [] }
12
+ @on_error = on_error
13
+ @returns = returns
14
+ end
15
+
16
+ def list?
17
+ @returns == :list
18
+ end
19
+
20
+ # Resolves params (with defaults + validation) then calls the fetch block.
21
+ def call(raw_params)
22
+ resolved = {}
23
+ params.each do |pname, spec|
24
+ resolved[pname] = spec.resolve(raw_params || {})
25
+ end
26
+ # Pass as keyword args if the block expects them, else positional.
27
+ if @fetch_block.parameters.any? { |type, _| type == :keyreq || type == :key }
28
+ @fetch_block.call(**resolved)
29
+ else
30
+ @fetch_block.call
31
+ end
32
+ end
33
+
34
+ # JSON-friendly description of the params for the editor's Data panel.
35
+ def param_schema
36
+ params.transform_values do |spec|
37
+ {
38
+ type: spec.type,
39
+ default: spec.default,
40
+ range: spec.range && [ spec.range.min, spec.range.max ],
41
+ allowed: spec.allowed
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ require "concurrent/map"
2
+
3
+ module ActiveCanvas
4
+ module DataSources
5
+ @registry = Concurrent::Map.new
6
+ @frozen = false
7
+
8
+ class << self
9
+ def register(name, &block)
10
+ name = name.to_sym
11
+ raise RegistryFrozen.new(name) if @frozen
12
+ builder = Registration.new(name)
13
+ builder.instance_eval(&block)
14
+ @registry[name] = builder.to_source
15
+ end
16
+
17
+ def lookup(name)
18
+ @registry[name.to_sym] || raise(UnknownSource.new(name))
19
+ end
20
+
21
+ def registered?(name)
22
+ @registry.key?(name.to_sym)
23
+ end
24
+
25
+ def registered_names
26
+ @registry.keys.sort
27
+ end
28
+
29
+ def each(&block)
30
+ @registry.each_pair(&block)
31
+ end
32
+
33
+ # Default loop variable for a binding: `articles` → `article`, and
34
+ # `item` when the singular is no different (`team`).
35
+ def item_name(name)
36
+ singular = name.to_s.singularize
37
+ singular.present? && singular != name.to_s ? singular : "item"
38
+ end
39
+
40
+ def freeze!
41
+ @frozen = true
42
+ end
43
+
44
+ def frozen?
45
+ @frozen
46
+ end
47
+
48
+ def reset_for_testing!
49
+ @registry = Concurrent::Map.new
50
+ @frozen = false
51
+ end
52
+ end
53
+ end
54
+ end
@@ -13,6 +13,14 @@ module ActiveCanvas
13
13
  app.config.assets.precompile += %w[
14
14
  active_canvas/editor.js
15
15
  active_canvas/editor.css
16
+ active_canvas/editor/ac_bindings.js
17
+ active_canvas/editor/ac_chips.js
18
+ active_canvas/editor/directive_traits.js
19
+ active_canvas/editor/template_validator.js
20
+ active_canvas/editor/live_data.js
21
+ active_canvas/admin/data_panel.js
22
+ active_canvas/admin/field_builder.js
23
+ active_canvas/admin/media_select_preview.js
16
24
  ]
17
25
  end
18
26
 
@@ -40,5 +48,12 @@ module ActiveCanvas
40
48
  end
41
49
  end
42
50
  end
51
+
52
+ # Freeze the data source registry after all after_initialize hooks have run
53
+ # (including the host app's own after_initialize blocks that register sources)
54
+ # so subsequent registration attempts raise loudly.
55
+ initializer "active_canvas.freeze_data_sources", after: :finisher_hook do
56
+ ActiveCanvas::DataSources.freeze!
57
+ end
43
58
  end
44
59
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveCanvas
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/active_canvas.rb CHANGED
@@ -1,5 +1,11 @@
1
+ require "liquid"
1
2
  require "active_canvas/version"
2
3
  require "active_canvas/configuration"
4
+ require "active_canvas/data_sources/errors"
5
+ require "active_canvas/data_sources/param_spec"
6
+ require "active_canvas/data_sources/source"
7
+ require "active_canvas/data_sources/registration"
8
+ require "active_canvas/data_sources"
3
9
  require "active_canvas/engine"
4
10
 
5
11
  # Load RubyLLM if available for AI features
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_canvas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Giovanni Panasiti
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-06-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -37,6 +37,34 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: liquid
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '5.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '5.4'
54
+ - !ruby/object:Gem::Dependency
55
+ name: csv
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
40
68
  description: ActiveCanvas provides a simple CMS for creating and managing static pages
41
69
  with an admin interface
42
70
  email:
@@ -48,18 +76,30 @@ files:
48
76
  - MIT-LICENSE
49
77
  - README.md
50
78
  - Rakefile
79
+ - app/assets/javascripts/active_canvas/admin/data_panel.js
80
+ - app/assets/javascripts/active_canvas/admin/field_builder.js
81
+ - app/assets/javascripts/active_canvas/admin/media_select_preview.js
51
82
  - app/assets/javascripts/active_canvas/editor.js
83
+ - app/assets/javascripts/active_canvas/editor/ac_bindings.js
84
+ - app/assets/javascripts/active_canvas/editor/ac_chips.js
52
85
  - app/assets/javascripts/active_canvas/editor/ai_panel.js
53
86
  - app/assets/javascripts/active_canvas/editor/asset_manager.js
54
87
  - app/assets/javascripts/active_canvas/editor/blocks.js
55
88
  - app/assets/javascripts/active_canvas/editor/code_panel.js
56
89
  - app/assets/javascripts/active_canvas/editor/component_toolbar.js
90
+ - app/assets/javascripts/active_canvas/editor/directive_traits.js
91
+ - app/assets/javascripts/active_canvas/editor/live_data.js
57
92
  - app/assets/javascripts/active_canvas/editor/panels.js
93
+ - app/assets/javascripts/active_canvas/editor/preview_modal.js
94
+ - app/assets/javascripts/active_canvas/editor/template_validator.js
58
95
  - app/assets/javascripts/active_canvas/editor/utils.js
59
96
  - app/assets/stylesheets/active_canvas/application.css
60
97
  - app/assets/stylesheets/active_canvas/editor.css
61
98
  - app/controllers/active_canvas/admin/ai_controller.rb
62
99
  - app/controllers/active_canvas/admin/application_controller.rb
100
+ - app/controllers/active_canvas/admin/collection_items_controller.rb
101
+ - app/controllers/active_canvas/admin/collections_controller.rb
102
+ - app/controllers/active_canvas/admin/form_submissions_controller.rb
63
103
  - app/controllers/active_canvas/admin/media_controller.rb
64
104
  - app/controllers/active_canvas/admin/page_types_controller.rb
65
105
  - app/controllers/active_canvas/admin/page_versions_controller.rb
@@ -67,19 +107,28 @@ files:
67
107
  - app/controllers/active_canvas/admin/partials_controller.rb
68
108
  - app/controllers/active_canvas/admin/settings_controller.rb
69
109
  - app/controllers/active_canvas/application_controller.rb
110
+ - app/controllers/active_canvas/form_submissions_controller.rb
70
111
  - app/controllers/active_canvas/pages_controller.rb
112
+ - app/controllers/active_canvas/redirects_controller.rb
71
113
  - app/controllers/concerns/active_canvas/current_user.rb
72
114
  - app/controllers/concerns/active_canvas/rate_limitable.rb
73
115
  - app/controllers/concerns/active_canvas/tailwind_compilation.rb
116
+ - app/helpers/active_canvas/admin/collection_items_helper.rb
74
117
  - app/helpers/active_canvas/application_helper.rb
75
118
  - app/jobs/active_canvas/application_job.rb
76
119
  - app/jobs/active_canvas/compile_tailwind_job.rb
77
120
  - app/mailers/active_canvas/application_mailer.rb
78
121
  - app/models/active_canvas/ai_model.rb
79
122
  - app/models/active_canvas/application_record.rb
123
+ - app/models/active_canvas/auto_drop.rb
124
+ - app/models/active_canvas/collection.rb
125
+ - app/models/active_canvas/collection_item.rb
126
+ - app/models/active_canvas/collection_item_version.rb
80
127
  - app/models/active_canvas/current.rb
128
+ - app/models/active_canvas/form_submission.rb
81
129
  - app/models/active_canvas/media.rb
82
130
  - app/models/active_canvas/page.rb
131
+ - app/models/active_canvas/page_redirect.rb
83
132
  - app/models/active_canvas/page_type.rb
84
133
  - app/models/active_canvas/page_version.rb
85
134
  - app/models/active_canvas/partial.rb
@@ -87,10 +136,30 @@ files:
87
136
  - app/services/active_canvas/ai_configuration.rb
88
137
  - app/services/active_canvas/ai_models.rb
89
138
  - app/services/active_canvas/ai_service.rb
139
+ - app/services/active_canvas/collection_schema.rb
140
+ - app/services/active_canvas/collection_source.rb
90
141
  - app/services/active_canvas/content_renderer.rb
91
142
  - app/services/active_canvas/content_sanitizer.rb
143
+ - app/services/active_canvas/form_schema.rb
144
+ - app/services/active_canvas/form_stamper.rb
92
145
  - app/services/active_canvas/media_ref_backfill.rb
93
146
  - app/services/active_canvas/tailwind_compiler.rb
147
+ - app/services/active_canvas/template_renderer.rb
148
+ - app/services/active_canvas/template_renderer/binding_resolver.rb
149
+ - app/services/active_canvas/template_renderer/directive_expander.rb
150
+ - app/views/active_canvas/admin/collection_items/_field_input.html.erb
151
+ - app/views/active_canvas/admin/collection_items/_form.html.erb
152
+ - app/views/active_canvas/admin/collection_items/edit.html.erb
153
+ - app/views/active_canvas/admin/collection_items/history.html.erb
154
+ - app/views/active_canvas/admin/collection_items/index.html.erb
155
+ - app/views/active_canvas/admin/collection_items/new.html.erb
156
+ - app/views/active_canvas/admin/collections/_field_builder.html.erb
157
+ - app/views/active_canvas/admin/collections/_form.html.erb
158
+ - app/views/active_canvas/admin/collections/edit.html.erb
159
+ - app/views/active_canvas/admin/collections/index.html.erb
160
+ - app/views/active_canvas/admin/collections/new.html.erb
161
+ - app/views/active_canvas/admin/form_submissions/index.html.erb
162
+ - app/views/active_canvas/admin/form_submissions/show.html.erb
94
163
  - app/views/active_canvas/admin/media/index.html.erb
95
164
  - app/views/active_canvas/admin/media/show.html.erb
96
165
  - app/views/active_canvas/admin/page_types/_form.html.erb
@@ -99,6 +168,7 @@ files:
99
168
  - app/views/active_canvas/admin/page_types/new.html.erb
100
169
  - app/views/active_canvas/admin/page_types/show.html.erb
101
170
  - app/views/active_canvas/admin/page_versions/show.html.erb
171
+ - app/views/active_canvas/admin/pages/_data_panel.html.erb
102
172
  - app/views/active_canvas/admin/pages/_form.html.erb
103
173
  - app/views/active_canvas/admin/pages/content.html.erb
104
174
  - app/views/active_canvas/admin/pages/edit.html.erb
@@ -119,9 +189,21 @@ files:
119
189
  - config/routes.rb
120
190
  - db/migrate/20260202000001_create_active_canvas_tables.rb
121
191
  - db/migrate/20260202000002_create_active_canvas_ai_models.rb
192
+ - db/migrate/20260517100001_add_template_enabled_and_bindings_to_active_canvas_pages.rb
193
+ - db/migrate/20260517100002_add_bindings_to_active_canvas_page_versions.rb
122
194
  - db/migrate/20260613000002_backfill_active_canvas_media_refs.rb
195
+ - db/migrate/20260702000001_create_active_canvas_page_redirects.rb
196
+ - db/migrate/20260702000002_create_active_canvas_form_submissions.rb
197
+ - db/migrate/20260702000003_create_active_canvas_collections.rb
198
+ - db/migrate/20260702000004_create_active_canvas_collection_items.rb
199
+ - db/migrate/20260702000005_create_active_canvas_collection_item_versions.rb
123
200
  - lib/active_canvas.rb
124
201
  - lib/active_canvas/configuration.rb
202
+ - lib/active_canvas/data_sources.rb
203
+ - lib/active_canvas/data_sources/errors.rb
204
+ - lib/active_canvas/data_sources/param_spec.rb
205
+ - lib/active_canvas/data_sources/registration.rb
206
+ - lib/active_canvas/data_sources/source.rb
125
207
  - lib/active_canvas/engine.rb
126
208
  - lib/active_canvas/version.rb
127
209
  - lib/generators/active_canvas/install/install_generator.rb
@@ -148,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
230
  - !ruby/object:Gem::Version
149
231
  version: '0'
150
232
  requirements: []
151
- rubygems_version: 3.6.2
233
+ rubygems_version: 4.0.16
152
234
  specification_version: 4
153
235
  summary: A mountable Rails CMS engine for managing static pages
154
236
  test_files: []