active_canvas 0.0.1 → 0.0.2
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 379f677cf18be6230e9307e1380a024d6252a4add2b2cd954dfa6769a91b2541
|
|
4
|
+
data.tar.gz: fb55ab3e7801bae61423982e903cf61d35c396fb523209154a730e67b6fe93ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f68e873c9f4950c4b11ecf7a673d4edf911a719bbea2f163e9da45809facebf2a5ec822293dd1077922106a507f4e017b1d1312ca7ab99a207a5212cae8fda2e
|
|
7
|
+
data.tar.gz: cfcb65632db1f023976acf5699880d615120f6ae669922c4f5c5d39cb0b61ce1daf0fed55a136e9b3b9d6e585d08143eca45b8446602f30b2dfa03686904eac2
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# ActiveCanvas
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
3
5
|
A mountable Rails engine that turns any Rails app into a full-featured CMS. Includes a visual drag-and-drop editor (GrapeJS), AI-powered content generation, Tailwind CSS compilation, media management, page versioning, and SEO controls -- all behind an admin interface that works out of the box.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
let cssMonacoEditor = null;
|
|
30
30
|
let jsMonacoEditor = null;
|
|
31
31
|
let monacoInitialized = false;
|
|
32
|
+
let isSyncing = false;
|
|
32
33
|
|
|
33
34
|
// Component editing mode
|
|
34
35
|
let editingComponent = null;
|
|
@@ -201,6 +202,7 @@
|
|
|
201
202
|
// Sync GrapeJS content to Monaco editors
|
|
202
203
|
function syncGrapeJSToMonaco() {
|
|
203
204
|
if (!monacoInitialized) return;
|
|
205
|
+
isSyncing = true;
|
|
204
206
|
|
|
205
207
|
if (isComponentMode && editingComponent) {
|
|
206
208
|
htmlMonacoEditor.setValue(editingComponent.toHTML());
|
|
@@ -208,7 +210,13 @@
|
|
|
208
210
|
htmlMonacoEditor.setValue(editor.getHtml());
|
|
209
211
|
}
|
|
210
212
|
cssMonacoEditor.setValue(editor.getCss());
|
|
211
|
-
setTimeout(
|
|
213
|
+
setTimeout(async () => {
|
|
214
|
+
try {
|
|
215
|
+
await formatAllCode();
|
|
216
|
+
} finally {
|
|
217
|
+
isSyncing = false;
|
|
218
|
+
}
|
|
219
|
+
}, 50);
|
|
212
220
|
}
|
|
213
221
|
|
|
214
222
|
// Update GrapeJS preview from Monaco
|
|
@@ -252,7 +260,9 @@
|
|
|
252
260
|
} catch (e) {
|
|
253
261
|
console.error('Error replacing component:', e);
|
|
254
262
|
try {
|
|
263
|
+
component.components().reset();
|
|
255
264
|
component.components(html);
|
|
265
|
+
editor.select(component);
|
|
256
266
|
} catch (e2) {
|
|
257
267
|
console.error('Error updating component content:', e2);
|
|
258
268
|
}
|
|
@@ -285,8 +295,15 @@
|
|
|
285
295
|
if (!monacoInitialized) {
|
|
286
296
|
initMonacoEditors();
|
|
287
297
|
setTimeout(() => {
|
|
298
|
+
isSyncing = true;
|
|
288
299
|
htmlMonacoEditor.setValue(component.toHTML());
|
|
289
|
-
setTimeout(() =>
|
|
300
|
+
setTimeout(async () => {
|
|
301
|
+
try {
|
|
302
|
+
await htmlMonacoEditor.getAction('editor.action.formatDocument').run();
|
|
303
|
+
} finally {
|
|
304
|
+
isSyncing = false;
|
|
305
|
+
}
|
|
306
|
+
}, 50);
|
|
290
307
|
|
|
291
308
|
document.getElementById('monaco-html-container').style.display = 'block';
|
|
292
309
|
document.getElementById('monaco-css-container').style.display = 'none';
|
|
@@ -296,8 +313,15 @@
|
|
|
296
313
|
htmlMonacoEditor.focus();
|
|
297
314
|
}, 200);
|
|
298
315
|
} else {
|
|
316
|
+
isSyncing = true;
|
|
299
317
|
htmlMonacoEditor.setValue(component.toHTML());
|
|
300
|
-
setTimeout(() =>
|
|
318
|
+
setTimeout(async () => {
|
|
319
|
+
try {
|
|
320
|
+
await htmlMonacoEditor.getAction('editor.action.formatDocument').run();
|
|
321
|
+
} finally {
|
|
322
|
+
isSyncing = false;
|
|
323
|
+
}
|
|
324
|
+
}, 50);
|
|
301
325
|
|
|
302
326
|
document.getElementById('monaco-html-container').style.display = 'block';
|
|
303
327
|
document.getElementById('monaco-css-container').style.display = 'none';
|
|
@@ -343,6 +367,8 @@
|
|
|
343
367
|
}
|
|
344
368
|
|
|
345
369
|
function scheduleCodeUpdate() {
|
|
370
|
+
if (isSyncing) return;
|
|
371
|
+
|
|
346
372
|
if (statusEl) {
|
|
347
373
|
statusEl.textContent = 'Modified...';
|
|
348
374
|
statusEl.className = 'code-status modified';
|
|
@@ -180,17 +180,22 @@
|
|
|
180
180
|
document.addEventListener('keydown', function(e) {
|
|
181
181
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
182
182
|
e.preventDefault();
|
|
183
|
+
if (document.activeElement && document.activeElement.closest('.monaco-editor')) return;
|
|
183
184
|
saveContent(false);
|
|
184
185
|
}
|
|
185
186
|
});
|
|
186
187
|
|
|
188
|
+
let saveInProgress = false;
|
|
189
|
+
|
|
187
190
|
// Auto-save every 60 seconds
|
|
188
191
|
setInterval(() => {
|
|
189
192
|
saveContent(true);
|
|
190
193
|
}, 60000);
|
|
191
194
|
|
|
192
195
|
function saveContent(isAutoSave) {
|
|
193
|
-
|
|
196
|
+
if (saveInProgress) return;
|
|
197
|
+
saveInProgress = true;
|
|
198
|
+
|
|
194
199
|
if (saveBtn) saveBtn.disabled = true;
|
|
195
200
|
|
|
196
201
|
const html = editor.getHtml();
|
|
@@ -243,6 +248,7 @@
|
|
|
243
248
|
console.error('Save error:', error);
|
|
244
249
|
})
|
|
245
250
|
.finally(() => {
|
|
251
|
+
saveInProgress = false;
|
|
246
252
|
if (saveBtn) saveBtn.disabled = false;
|
|
247
253
|
});
|
|
248
254
|
}
|
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.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Giovanni Panasiti
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-04-30 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|