active_canvas 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6178be7aae3ee9f6da228b4d3aa8e0927c4faf622a7215b313616f4fda4d87d
4
- data.tar.gz: 64b25a9e874d070f4289013c8d66cc1a3896fbf35bab1189f80ab84e01790593
3
+ metadata.gz: 72294f59d8513e96f33a6320c30e07ff22a94a404c7184145dd3ec0f2720c620
4
+ data.tar.gz: 6bdb95ac11f18b17de836347fa6a701dd2160e31da5792eef809d4231546b6b5
5
5
  SHA512:
6
- metadata.gz: 69e71f2fea7ea67db2f3ae3dabb864b1f6c8234b45a7e3529315c0b65075b31ed7fa9837528e1fda7072a841987437f3a7a0f006c1b5a3bdcf3a3b8c26b2e660
7
- data.tar.gz: a5853a4a2d3b35422238b281a44951a90fbff0d92e245546df70c06e2a618e5c1941cbce7b9e5ca2209b4dd4d5f4be9efd37e22cc25c22c9f9fa54a15aee7bc5
6
+ metadata.gz: d9b3065b225b1b0a6775920d27a536adec1905520f78bc9242362d578462a5a552aabeb399ff8e06af570801d186e0bf6061da05f2a8b031a5834a39c034e054
7
+ data.tar.gz: ab54bbe8bfafc2cb60900c11bfa4f02716f81742bffa3eea7c623d9c91ab1aeada485197eb968cd605e7cb17e6676f17c73a965f8c753e224f5789f0f7b04562
@@ -354,6 +354,13 @@
354
354
  frame.contentDocument.body.appendChild(globalScript);
355
355
  }
356
356
 
357
+ // Inject custom <head> HTML (fonts, CDN CSS, meta) into the preview.
358
+ // insertAdjacentHTML applies <link>/<meta>/<style> so fonts/CSS show in
359
+ // the editor; external <script src> does not execute in the preview (by design).
360
+ if (config.customHeadHtml && config.customHeadHtml.trim()) {
361
+ frame.contentDocument.head.insertAdjacentHTML('beforeend', config.customHeadHtml);
362
+ }
363
+
357
364
  // Inject page-specific JS
358
365
  if (config.contentJs && config.contentJs.trim()) {
359
366
  const script = frame.contentDocument.createElement('script');
@@ -7,6 +7,7 @@ module ActiveCanvas
7
7
  @css_framework = Setting.css_framework
8
8
  @global_css = Setting.global_css
9
9
  @global_js = Setting.global_js
10
+ @custom_head_html = Setting.custom_head_html
10
11
  @pages = Page.published.order(:title)
11
12
 
12
13
  # Tailwind settings
@@ -71,6 +72,15 @@ module ActiveCanvas
71
72
  end
72
73
  end
73
74
 
75
+ def update_custom_head
76
+ Setting.custom_head_html = params[:custom_head_html]
77
+
78
+ respond_to do |format|
79
+ format.html { redirect_to admin_settings_path(tab: "scripts"), notice: "Custom head HTML saved." }
80
+ format.json { render json: { success: true, message: "Custom head HTML saved." } }
81
+ end
82
+ end
83
+
74
84
  def update_ai
75
85
  # API Keys - only update if a new value is provided (not empty, not masked)
76
86
  update_api_key("ai_openai_api_key", params[:ai_openai_api_key])
@@ -181,6 +181,14 @@ module ActiveCanvas
181
181
  set("global_js", js)
182
182
  end
183
183
 
184
+ def custom_head_html
185
+ get("custom_head_html") || ""
186
+ end
187
+
188
+ def custom_head_html=(html)
189
+ set("custom_head_html", html)
190
+ end
191
+
184
192
  # AI API Keys
185
193
  def ai_openai_api_key
186
194
  get("ai_openai_api_key")
@@ -612,6 +612,7 @@
612
612
  tailwindConfig: <%= raw ActiveCanvas::Setting.tailwind_config_js %>,
613
613
  globalCss: <%= raw (ActiveCanvas::Setting.global_css || '').to_json %>,
614
614
  globalJs: <%= raw (ActiveCanvas::Setting.global_js || '').to_json %>,
615
+ customHeadHtml: <%= raw (ActiveCanvas::Setting.custom_head_html || '').to_json %>,
615
616
  aiConnectionMode: '<%= ActiveCanvas::Setting.ai_connection_mode %>',
616
617
  <% if ActiveCanvas::Setting.ai_connection_mode == "direct" %>
617
618
  aiApiKeys: {
@@ -613,6 +613,7 @@
613
613
  tailwindConfig: <%= raw ActiveCanvas::Setting.tailwind_config_js %>,
614
614
  globalCss: <%= raw (ActiveCanvas::Setting.global_css || '').to_json %>,
615
615
  globalJs: <%= raw (ActiveCanvas::Setting.global_js || '').to_json %>,
616
+ customHeadHtml: <%= raw (ActiveCanvas::Setting.custom_head_html || '').to_json %>,
616
617
  aiEndpoints: {
617
618
  status: '<%= admin_ai_status_path %>',
618
619
  models: '<%= admin_ai_models_path %>',
@@ -410,6 +410,67 @@
410
410
  }
411
411
  </style>
412
412
  <% elsif @active_tab == "scripts" %>
413
+ <div class="card settings-code-card">
414
+ <div class="settings-code-header">
415
+ <h3>Custom &lt;head&gt; HTML</h3>
416
+ <p class="help-text" style="margin-top: 0;">
417
+ Injected verbatim into the &lt;head&gt; of every published page (fonts, CDN links, meta tags, third-party scripts).
418
+ Also shown in the editor preview (external scripts do not execute in the preview; fonts/CSS/meta do).
419
+ If your app enforces a strict Content-Security-Policy, external resources added here may be blocked.
420
+ </p>
421
+ </div>
422
+ <textarea id="custom-head-html-input" class="form-control" rows="10" spellcheck="false"
423
+ style="font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; width: 100%;"
424
+ placeholder="&lt;link rel=&quot;preconnect&quot; href=&quot;https://fonts.googleapis.com&quot;&gt;
425
+ &lt;link href=&quot;https://fonts.googleapis.com/css2?family=Inter&amp;display=swap&quot; rel=&quot;stylesheet&quot;&gt;
426
+ &lt;meta name=&quot;theme-color&quot; content=&quot;#000000&quot;&gt;
427
+ &lt;script src=&quot;https://cdn.example.com/lib.js&quot;&gt;&lt;/script&gt;"><%= @custom_head_html %></textarea>
428
+ <div class="settings-code-actions">
429
+ <button type="button" id="save-custom-head-btn" class="btn btn-primary">
430
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
431
+ <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
432
+ <polyline points="17 21 17 13 7 13 7 21"/>
433
+ <polyline points="7 3 7 8 15 8"/>
434
+ </svg>
435
+ Save Custom Head HTML
436
+ </button>
437
+ </div>
438
+ </div>
439
+
440
+ <script>
441
+ (function() {
442
+ var btn = document.getElementById('save-custom-head-btn');
443
+ var input = document.getElementById('custom-head-html-input');
444
+ if (!btn || !input) return;
445
+ var csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
446
+ var defaultLabel = btn.innerHTML;
447
+
448
+ btn.addEventListener('click', function() {
449
+ btn.disabled = true;
450
+ btn.textContent = 'Saving...';
451
+ fetch('<%= update_custom_head_admin_settings_path %>', {
452
+ method: 'PATCH',
453
+ headers: {
454
+ 'Content-Type': 'application/json',
455
+ 'X-CSRF-Token': csrfToken,
456
+ 'Accept': 'application/json'
457
+ },
458
+ body: JSON.stringify({ custom_head_html: input.value })
459
+ })
460
+ .then(function(r) { return r.json(); })
461
+ .then(function(result) {
462
+ btn.textContent = result.success ? 'Saved!' : 'Error';
463
+ setTimeout(function() { btn.disabled = false; btn.innerHTML = defaultLabel; }, 2000);
464
+ })
465
+ .catch(function(e) {
466
+ btn.disabled = false;
467
+ btn.innerHTML = defaultLabel;
468
+ console.error('Save error:', e);
469
+ });
470
+ });
471
+ })();
472
+ </script>
473
+
413
474
  <div class="card settings-code-card">
414
475
  <div class="settings-code-header">
415
476
  <h3>Global JavaScript</h3>
@@ -43,6 +43,10 @@
43
43
  <% if ActiveCanvas::Setting.global_css.present? %>
44
44
  <style><%= ActiveCanvas::Setting.global_css.html_safe %></style>
45
45
  <% end %>
46
+
47
+ <% if ActiveCanvas::Setting.custom_head_html.present? %>
48
+ <%= ActiveCanvas::Setting.custom_head_html.html_safe %>
49
+ <% end %>
46
50
  </head>
47
51
  <body>
48
52
 
data/config/routes.rb CHANGED
@@ -21,6 +21,7 @@ ActiveCanvas::Engine.routes.draw do
21
21
  resource :settings, only: [:show, :update] do
22
22
  patch :update_global_css
23
23
  patch :update_global_js
24
+ patch :update_custom_head
24
25
  patch :update_ai
25
26
  post :sync_ai_models
26
27
  patch :toggle_ai_model
@@ -1,3 +1,3 @@
1
1
  module ActiveCanvas
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_canvas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Giovanni Panasiti