alchemy-widget 0.2.8 → 0.3.0-alpha.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.3.0-alpha.2 (2025-07-10)
2
+
3
+ * Make `main_class_names` widget config add classes to the first child of the wrapper
4
+ * Add `li_class_names` config to List widgets
5
+ * Don't return client-version of ToolbarManager on the server
6
+
7
+ ## 0.3.0-alpha.1 (2024-02-15)
8
+
9
+ * Upgrade to Alchemy v1.4.0
10
+
1
11
  ## 0.2.8 (2023-06-17)
2
12
 
3
13
  * Make the widget toolbar render area contents correctly + load scripts & styles
File without changes
package/bootstrap.js CHANGED
@@ -3,107 +3,3 @@ alchemy.requirePlugin('form', false);
3
3
  if (!alchemy.plugins.form) {
4
4
  throw new Error('The alchemy-form plugin has to be loaded BEFORE alchemy-widget');
5
5
  }
6
-
7
- /* Ckeditor 5 available toolbar buttons (from styleboost build)
8
- [
9
- "blockQuote",
10
- "bold",
11
- "code",
12
- "codeBlock",
13
- "selectAll",
14
- "undo",
15
- "redo",
16
- "heading",
17
- "horizontalLine",
18
- "imageTextAlternative",
19
- "toggleImageCaption",
20
- "imageStyle:inline",
21
- "imageStyle:alignLeft",
22
- "imageStyle:alignRight",
23
- "imageStyle:alignCenter",
24
- "imageStyle:alignBlockLeft",
25
- "imageStyle:alignBlockRight",
26
- "imageStyle:block",
27
- "imageStyle:side",
28
- "imageStyle:wrapText",
29
- "imageStyle:breakText",
30
- "uploadImage",
31
- "imageUpload",
32
- "indent",
33
- "outdent",
34
- "italic",
35
- "link",
36
- "linkImage",
37
- "numberedList",
38
- "bulletedList",
39
- "mediaEmbed",
40
- "removeFormat",
41
- "sourceEditing",
42
- "strikethrough",
43
- "insertTable",
44
- "tableColumn",
45
- "tableRow",
46
- "mergeTableCells",
47
- "toggleTableCaption",
48
- "tableCellProperties",
49
- "tableProperties",
50
- "todoList"
51
- ]
52
- */
53
-
54
- let options = {
55
- ckeditor_path: null,
56
- ckeditor_toolbar: [
57
- 'heading',
58
- '|',
59
- 'bold', 'italic', 'link', 'bulletedList', 'numberedList',
60
- '|',
61
- 'indent',
62
- 'outdent',
63
- 'horizontalLine',
64
- '|',
65
- 'blockQuote',
66
- 'code',
67
- 'codeBlock',
68
- '|',
69
- 'imageUpload',
70
- 'insertTable',
71
- '|',
72
- 'undo', 'redo',
73
- ],
74
- };
75
-
76
- // Inject the user-overridden options
77
- alchemy.plugins.widget = Object.assign(options, alchemy.plugins.widget);
78
-
79
- if (!options.ckeditor_path) {
80
- if (alchemy.plugins.styleboost) {
81
- options.ckeditor_path = '/public/ckeditor/5/ckeditor.js';
82
- } else {
83
- options.ckeditor_path = 'https://cdn.ckeditor.com/ckeditor5/35.3.2/inline/ckeditor.js';
84
- }
85
- }
86
-
87
- if (options.ckeditor_path) {
88
- alchemy.exposeStatic('ckeditor_path', options.ckeditor_path);
89
- }
90
-
91
- if (options.ckeditor_toolbar) {
92
- alchemy.exposeStatic('ckeditor_toolbar', options.ckeditor_toolbar);
93
- }
94
-
95
- Router.add({
96
- name : 'AlchemyWidgets#save',
97
- methods : 'post',
98
- paths : '/api/alchemywidgets/save',
99
- policy : 'logged_in',
100
- permission : 'alchemy.widgets.save',
101
- });
102
-
103
- Router.add({
104
- name : 'AlchemyWidgets#uploadImage',
105
- methods : 'post',
106
- paths : '/api/alchemywidgets/upload',
107
- policy : 'logged_in',
108
- permission : 'alchemy.widgets.image.upload',
109
- });
@@ -0,0 +1,15 @@
1
+ Plugin.addRoute({
2
+ name : 'AlchemyWidgets#save',
3
+ methods : 'post',
4
+ paths : '/api/alchemywidgets/save',
5
+ policy : 'logged_in',
6
+ permission : 'alchemy.widgets.save',
7
+ });
8
+
9
+ Plugin.addRoute({
10
+ name : 'AlchemyWidgets#uploadImage',
11
+ methods : 'post',
12
+ paths : '/api/alchemywidgets/upload',
13
+ policy : 'logged_in',
14
+ permission : 'alchemy.widgets.image.upload',
15
+ });
@@ -0,0 +1,26 @@
1
+ const WIDGET_PLUGIN_GROUP = Plugin.getSettingsGroup();
2
+
3
+ const CKEDITOR = WIDGET_PLUGIN_GROUP.createGroup('ckeditor');
4
+
5
+ CKEDITOR.addSetting('path', {
6
+ type : 'string',
7
+ default : alchemy.plugins.styleboost ? '/public/ckeditor/5/ckeditor.js' : 'https://cdn.ckeditor.com/ckeditor5/35.3.2/inline/ckeditor.js',
8
+ description : 'The location of the ckeditor script',
9
+ action : (value, value_instance) => {
10
+ alchemy.exposeStatic('ckeditor_path', value);
11
+ },
12
+ });
13
+
14
+ CKEDITOR.addSetting('toolbar', {
15
+ type : 'string',
16
+ default : 'heading | bold italic link bulletedList numberedList | indent outdent horizontalLine | blockQuote code codeBlock | imageUpload insertTable | undo redo',
17
+ description : 'The location of the ckeditor script',
18
+ action : (value, value_instance) => {
19
+
20
+ if (value) {
21
+ value = value.split(' ');
22
+ }
23
+
24
+ alchemy.exposeStatic('ckeditor_toolbar', value);
25
+ },
26
+ });
@@ -46,6 +46,28 @@ TableOfContents.setAssignedProperty('content');
46
46
  */
47
47
  TableOfContents.setRole('navigation');
48
48
 
49
+ /**
50
+ * The element to use for the containers
51
+ *
52
+ * @author Jelle De Loecker <jelle@elevenways.be>
53
+ * @since 0.3.0
54
+ * @version 0.3.0
55
+ */
56
+ TableOfContents.setAttribute('container-element', function getValue(value) {
57
+ return value || 'ol';
58
+ });
59
+
60
+ /**
61
+ * The element to use for the entries
62
+ *
63
+ * @author Jelle De Loecker <jelle@elevenways.be>
64
+ * @since 0.3.0
65
+ * @version 0.3.0
66
+ */
67
+ TableOfContents.setAttribute('entry-element', function getValue(value) {
68
+ return value || 'li';
69
+ });
70
+
49
71
  /**
50
72
  * The parent query
51
73
  *
@@ -105,7 +127,7 @@ TableOfContents.setAttribute('truncate-length', {type: 'number'});
105
127
  *
106
128
  * @author Jelle De Loecker <jelle@elevenways.be>
107
129
  * @since 0.1.2
108
- * @version 0.2.4
130
+ * @version 0.3.0
109
131
  */
110
132
  TableOfContents.setProperty(function entries() {
111
133
 
@@ -159,7 +181,9 @@ TableOfContents.setProperty(function entries() {
159
181
  title_element = heading;
160
182
  }
161
183
 
162
- if (title_element.nodeName[0] == 'H' && isFinite(title_element.nodeName[1])) {
184
+ if (title_element.dataset.toc_level > 0) {
185
+ heading_level = +title_element.dataset.toc_level;
186
+ } else if (title_element.nodeName[0] == 'H' && isFinite(title_element.nodeName[1])) {
163
187
  heading_level = +title_element.nodeName[1];
164
188
  } else if (!heading_level) {
165
189
  heading_level = 1;
@@ -146,7 +146,7 @@ EditorToolbarManager.setMethod(function queueModelFallback(model_name) {
146
146
  *
147
147
  * @author Jelle De Loecker <jelle@elevenways.be>
148
148
  * @since 0.2.7
149
- * @version 0.2.7
149
+ * @version 0.3.0
150
150
  *
151
151
  * @param {String} model_name
152
152
  */
@@ -164,7 +164,7 @@ EditorToolbarManager.setTypedMethod([Types.String.optional().nullable()], functi
164
164
 
165
165
  if (Blast.isNode && model_name) {
166
166
  this.addTemplateToRender('buttons', 'chimera/toolbar/create_button', {
167
- model_name: model_name.underscore(),
167
+ model_name: Blast.parseClassPath(model_name).map(entry => entry.underscore()).join('.'),
168
168
  });
169
169
  }
170
170
  });
@@ -740,7 +740,7 @@ Widget.setMethod(function populateWidget() {
740
740
  *
741
741
  * @author Jelle De Loecker <jelle@elevenways.be>
742
742
  * @since 0.1.0
743
- * @version 0.2.1
743
+ * @version 0.3.0
744
744
  */
745
745
  Widget.setMethod(function finalizePopulatedWidget() {
746
746
 
@@ -758,6 +758,22 @@ Widget.setMethod(function finalizePopulatedWidget() {
758
758
  }
759
759
  }
760
760
 
761
+ if (config.main_class_names) {
762
+ let main = this.widget?.children?.[0];
763
+
764
+ if (main) {
765
+ let name,
766
+ i;
767
+
768
+ let class_names = Array.cast(config.main_class_names);
769
+
770
+ for (i = 0; i < class_names.length; i++) {
771
+ name = class_names[i];
772
+ main.classList.add(name);
773
+ }
774
+ }
775
+ }
776
+
761
777
  if (config.language) {
762
778
  this.widget.setAttribute('lang', config.language);
763
779
  } else {
@@ -11,6 +11,23 @@
11
11
  */
12
12
  const List = Function.inherits('Alchemy.Widget.Container', 'List');
13
13
 
14
+ /**
15
+ * Prepare the schema
16
+ *
17
+ * @author Jelle De Loecker <jelle@elevenways.be>
18
+ * @since 0.3.0
19
+ * @version 0.3.0
20
+ */
21
+ List.constitute(function prepareSchema() {
22
+
23
+ // Classnames for the li elements
24
+ this.schema.addField('li_class_names', 'String', {
25
+ title : 'Li-element CSS classes',
26
+ description : 'Configure extra CSS classes for the list items',
27
+ array: true,
28
+ });
29
+ });
30
+
14
31
  /**
15
32
  * Get a list of elements that could be child widgets
16
33
  *
@@ -39,4 +56,38 @@ List.setMethod(function initContainer() {
39
56
  this.widget.list_element = ul;
40
57
 
41
58
  initContainer.super.call(this);
59
+ });
60
+
61
+ /**
62
+ * Populate the contents of the widget
63
+ *
64
+ * @author Jelle De Loecker <jelle@elevenways.be>
65
+ * @since 0.3.0
66
+ * @version 0.3.0
67
+ */
68
+ List.setMethod(function finalizePopulatedWidget() {
69
+
70
+ const config = this.config;
71
+
72
+ if (config?.li_class_names) {
73
+ let li_elements = this.widget.list_element.querySelectorAll(':scope > li');
74
+
75
+ if (li_elements.length) {
76
+ let name,
77
+ i;
78
+
79
+ let class_names = Array.cast(config.li_class_names);
80
+
81
+ for (i = 0; i < class_names.length; i++) {
82
+ name = class_names[i];
83
+
84
+ for (let li_element of li_elements) {
85
+ li_element.classList.add(name);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+
92
+ return finalizePopulatedWidget.super.call(this);
42
93
  });
@@ -1,3 +1,5 @@
1
+ const MANAGER = Symbol('toolbar_manager');
2
+
1
3
  /**
2
4
  * Add a method to the conduit class to set the toolbar manager
3
5
  *
@@ -13,6 +15,8 @@ Classes.Alchemy.Conduit.Conduit.setMethod(function setToolbarInfo(document_or_mo
13
15
  } catch (err) {
14
16
  console.error('Error setting toolbar info', err);
15
17
  }
18
+
19
+ return this[MANAGER];
16
20
  });
17
21
 
18
22
  /**
@@ -30,11 +34,18 @@ function _setToolbarInfo(document_or_model, scenario = 'frontend') {
30
34
  return;
31
35
  }
32
36
 
33
- let manager = Classes.Alchemy.Widget.EditorToolbarManager.create(this);
34
- manager.scenario = scenario;
37
+ let manager = this[MANAGER] || this.set('toolbar_manager');
38
+
39
+ if (!manager) {
40
+ manager = Classes.Alchemy.Widget.EditorToolbarManager.create(this);
41
+ this[MANAGER] = manager;
42
+ this.set('toolbar_manager', manager);
43
+ this.expose('toolbar_manager', manager);
44
+ }
35
45
 
36
- this.set('toolbar_manager', manager);
37
- this.expose('toolbar_manager', manager);
46
+ if (scenario !== undefined) {
47
+ manager.scenario = scenario;
48
+ }
38
49
 
39
50
  let document_watcher,
40
51
  document,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-widget",
3
3
  "description": "The widget plugin for the AlchemyMVC",
4
- "version": "0.2.8",
4
+ "version": "0.3.0-alpha.2",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",
@@ -10,8 +10,8 @@
10
10
  "widget"
11
11
  ],
12
12
  "peerDependencies": {
13
- "alchemymvc" : ">=1.3.0",
14
- "alchemy-form": "~0.2.6"
13
+ "alchemymvc" : ">=1.4.0||>=1.4.0-alpha",
14
+ "alchemy-form": "~0.3.0||~0.3.0-alpha"
15
15
  },
16
16
  "repository": "11ways/alchemy-widget",
17
17
  "license": "MIT",
@@ -1,25 +1,24 @@
1
1
  <% all_entries = self.tree %>
2
2
 
3
3
  {% macro printEntries %}
4
- <ol>
4
+ <% this.printElement(self.container_element) %>
5
+ <% if (is_child) $0.classList.add('toc-is-child') %>
5
6
  {% each entries as entry %}
6
7
  {% run printEntry entry=entry %}
7
-
8
- {% if entry.children %}
9
- <li>
10
- {% run printEntries entries=entry.children %}
11
- </li>
12
- {% /if %}
13
8
  {% /each %}
14
- </ol>
9
+ <% this.closeElement(self.container_element) %>
15
10
  {% /macro %}
16
11
 
17
12
  {% macro printEntry %}
18
- <li>
13
+ <% this.printElement(self.entry_element) %>
19
14
  <a href="#{% entry.id %}">
20
15
  {{ entry.title }}
21
16
  </a>
22
- </li>
17
+
18
+ {% if entry.children %}
19
+ {% run printEntries entries=entry.children is_child=true %}
20
+ {% /if %}
21
+ <% this.closeElement(self.entry_element) %>
23
22
  {% /macro %}
24
23
 
25
24
  {% run printEntries entries=all_entries %}