domma-cms 1.6.60 → 1.7.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.
- package/CHANGELOG.md +4344 -0
- package/README.md +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/lib/effect-defs.js +1 -1
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/page-editor-reference.js +5 -5
- package/admin/js/lib/shortcode-tags.js +1 -1
- package/admin/js/templates/docs/usage-shortcodes.html +39 -0
- package/docs/DommaFeatures.md +3005 -0
- package/docs/MultiTenant.md +176 -0
- package/docs/api-reference.md +1667 -0
- package/docs/cache.md +96 -0
- package/docs/configuration.md +1811 -0
- package/docs/editions-and-licences.md +190 -0
- package/docs/getting-started.md +201 -0
- package/docs/guides/form-triggers.md +260 -0
- package/docs/guides/mongodb-storage-adapter.md +282 -0
- package/docs/guides/multi-page-forms.md +121 -0
- package/docs/images/scribe-composer.png +0 -0
- package/docs/markdown-shortcodes.md +1738 -0
- package/docs/pentest-report-2026-04-03.md +181 -0
- package/docs/plans/2026-02-28-admin-topbar-login-forms.md +349 -0
- package/docs/plans/2026-02-28-domma-ui-polish.md +286 -0
- package/docs/plans/2026-02-28-reset-seed-fresh-commands.md +520 -0
- package/docs/plans/2026-03-02-cookie-consent-design.md +86 -0
- package/docs/plans/2026-03-02-cookie-consent-plugin.md +453 -0
- package/docs/plans/2026-03-02-tooltip-sweep-and-back-to-top-plugin-design.md +126 -0
- package/docs/plans/2026-03-02-tooltip-sweep-back-to-top.md +427 -0
- package/docs/plans/2026-03-05-cookie-consent-btt-core.md +115 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core-design.md +35 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core.md +352 -0
- package/docs/plans/2026-03-05-scribe-script-shortcode.md +373 -0
- package/docs/plans/2026-03-05-user-types-design.md +139 -0
- package/docs/plans/2026-03-05-user-types-implementation.md +1035 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts-design.md +78 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts.md +388 -0
- package/docs/plans/2026-03-09-pro-documentation-design.md +80 -0
- package/docs/plans/2026-03-09-pro-documentation.md +1017 -0
- package/docs/plans/2026-06-10-core-project-design.md +240 -0
- package/docs/plugin-development.md +827 -0
- package/docs/recruitment-recipe.md +501 -0
- package/docs/scaffolding.md +312 -0
- package/docs/screenshots/calculator-floating.png +0 -0
- package/docs/screenshots/calculator-standard.png +0 -0
- package/docs/screenshots/email-settings.png +0 -0
- package/docs/screenshots/messages-count.png +0 -0
- package/docs/structure/user-types.md +107 -0
- package/docs/superpowers/plans/2026-05-25-admin-sidebar-via-menus.md +1112 -0
- package/docs/superpowers/plans/2026-06-08-navbar-mobile-drawer-and-menu-enrichment.md +1161 -0
- package/docs/superpowers/plans/2026-06-25-domma-docs-project.md +695 -0
- package/docs/superpowers/plans/2026-06-26-surveys-HANDOFF.md +68 -0
- package/docs/superpowers/plans/2026-06-26-surveys-pro-plugin.md +1902 -0
- package/docs/superpowers/plans/2026-08-19-collection-context-sort-export.md +1577 -0
- package/docs/superpowers/plans/2026-10-09-content-api.md +1192 -0
- package/docs/superpowers/specs/2026-03-12-form-followup-actions-design.md +152 -0
- package/docs/superpowers/specs/2026-03-12-page-editor-form-insert-and-per-page-theme-design.md +115 -0
- package/docs/superpowers/specs/2026-03-17-nav-hidden-items-design.md +85 -0
- package/docs/superpowers/specs/2026-03-19-accordion-insert-design.md +175 -0
- package/docs/superpowers/specs/2026-03-25-static-block-shortcode-design.md +153 -0
- package/docs/superpowers/specs/2026-03-25-text-shortcode-design.md +168 -0
- package/docs/superpowers/specs/2026-04-05-card-builder-design.md +315 -0
- package/docs/superpowers/specs/2026-04-06-insert-builders-design.md +278 -0
- package/docs/superpowers/specs/2026-04-06-layouts-design.md +226 -0
- package/docs/superpowers/specs/2026-04-07-blog-plugin-design.md +300 -0
- package/docs/superpowers/specs/2026-04-07-calendar-plugin-design.md +538 -0
- package/docs/superpowers/specs/2026-04-17-components-area-design.md +368 -0
- package/docs/superpowers/specs/2026-05-02-effects-slideover-overhaul-design.md +193 -0
- package/docs/superpowers/specs/2026-05-06-dashboard-rebuild-design.md +257 -0
- package/docs/superpowers/specs/2026-05-24-menus-design.md +466 -0
- package/docs/superpowers/specs/2026-05-25-admin-sidebar-via-menus-design.md +358 -0
- package/docs/superpowers/specs/2026-05-25-projects-design.md +380 -0
- package/docs/superpowers/specs/2026-06-08-navbar-mobile-drawer-and-menu-enrichment-design.md +292 -0
- package/docs/superpowers/specs/2026-06-08-sidebar-tools-plugins-folders-design.md +59 -0
- package/docs/superpowers/specs/2026-06-25-domma-docs-project-design.md +192 -0
- package/docs/superpowers/specs/2026-06-26-domma-charts-upstream-proposal.md +44 -0
- package/docs/superpowers/specs/2026-06-26-manager-scheduler-upstream-proposal.md +46 -0
- package/docs/superpowers/specs/2026-06-26-surveys-pro-plugin-design.md +206 -0
- package/docs/superpowers/specs/2026-07-02-shortcode-context-menu-design.md +96 -0
- package/docs/superpowers/specs/2026-08-19-collection-context-sort-export-design.md +330 -0
- package/docs/superpowers/specs/2026-09-22-dcms-marketplace-design.md +1150 -0
- package/docs/superpowers/specs/2026-10-09-content-api-design.md +325 -0
- package/docs/superpowers/specs/plans/2026-03-12-form-followup-actions.md +624 -0
- package/docs/superpowers/specs/plans/2026-03-12-page-editor-form-insert-and-per-page-theme.md +125 -0
- package/docs/superpowers/specs/plans/2026-03-17-nav-hidden-items.md +578 -0
- package/docs/superpowers/specs/plans/2026-03-19-accordion-insert.md +635 -0
- package/docs/superpowers/specs/plans/2026-03-25-text-shortcode.md +545 -0
- package/docs/superpowers/specs/plans/2026-04-05-card-builder.md +1970 -0
- package/docs/superpowers/specs/plans/2026-04-06-insert-builders.md +1049 -0
- package/docs/superpowers/specs/plans/2026-04-06-layouts.md +1015 -0
- package/docs/superpowers/specs/plans/2026-04-07-calendar-plugin.md +1526 -0
- package/docs/superpowers/specs/plans/2026-04-08-plugin-monetisation-split.md +242 -0
- package/docs/superpowers/specs/plans/2026-04-17-components-area.md +2038 -0
- package/docs/superpowers/specs/plans/2026-05-02-effects-slideover-overhaul.md +2335 -0
- package/docs/superpowers/specs/plans/2026-05-06-dashboard-rebuild.md +1999 -0
- package/docs/superpowers/specs/plans/2026-05-17-cache-system.md +1436 -0
- package/docs/superpowers/specs/plans/2026-05-24-menus.md +3096 -0
- package/docs/superpowers/specs/plans/2026-05-25-projects.md +2869 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step2-consolidation.md +505 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step3-catalogue-and-key.md +154 -0
- package/docs/superpowers/specs/plans/2026-09-22-tools-promotion.md +260 -0
- package/docs/theming.md +320 -0
- package/package.json +2 -2
- package/public/js/celebrations/core/canvas.js +1 -1
- package/public/js/celebrations/index.js +1 -1
- package/public/js/celebrations/licenses/ABeeZee-Regular-OFL.txt +93 -0
- package/public/js/celebrations/licenses/Allura-Regular-OFL.txt +93 -0
- package/public/js/celebrations/message-attrs.mjs +1 -0
- package/public/js/celebrations/themes/anniversary.js +1 -0
- package/public/js/celebrations/themes/autumn.js +1 -0
- package/public/js/celebrations/themes/birthday.js +1 -0
- package/public/js/celebrations/themes/butterfly-flight.js +1 -0
- package/public/js/celebrations/themes/calendar.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year-dates.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year.js +1 -0
- package/public/js/celebrations/themes/christmas.js +1 -1
- package/public/js/celebrations/themes/easter.js +1 -0
- package/public/js/celebrations/themes/garden-drawing.js +1 -0
- package/public/js/celebrations/themes/garden.js +1 -0
- package/public/js/celebrations/themes/graduation.js +1 -0
- package/public/js/celebrations/themes/greeting.js +1 -0
- package/public/js/celebrations/themes/make-it-rain.js +1 -0
- package/public/js/celebrations/themes/money-rain.js +1 -0
- package/public/js/celebrations/themes/new-year.js +1 -0
- package/public/js/celebrations/themes/occasion-drawing.js +1 -0
- package/public/js/celebrations/themes/occasions.js +1 -0
- package/public/js/celebrations/themes/rain-control.js +1 -0
- package/public/js/celebrations/themes/sparkler-font-data.js +1 -0
- package/public/js/celebrations/themes/sparkler-font.js +1 -0
- package/public/js/celebrations/themes/sparkler-writing.js +1 -0
- package/public/js/celebrations/themes/summer-garden.js +1 -0
- package/public/js/celebrations/themes/winter.js +1 -0
- package/public/js/celebrations/trait-data.mjs +1 -1
- package/public/js/effects.js +1 -1
- package/scripts/build.js +4 -0
- package/server/services/markdown.js +5 -2
- package/server/templates/page.html +1 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Design Spec: `[text]` Shortcode
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-25
|
|
4
|
+
**Status:** Approved
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Add a `[text]` shortcode that renders a `<span>` with inline styles, giving content authors a simple, readable way to
|
|
9
|
+
apply rich text formatting directly in Markdown without writing raw HTML.
|
|
10
|
+
|
|
11
|
+
The shortcode is accessible via the existing Page Editor Insert icon menu (the `plus-circle` dropdown), which opens a
|
|
12
|
+
modal letting users configure options and preview the result before inserting.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Shortcode Syntax
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
[text size="xl" bold italic color="primary" font="Georgia"]Your text[/text]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Renders:
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<span style="font-size:1.25rem;font-weight:700;font-style:italic;color:var(--dm-color-primary);font-family:Georgia,serif;">Your text</span>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Only attributes that differ from defaults are emitted. All attributes are optional. Paired syntax only - no self-closing
|
|
29
|
+
form.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Supported Attributes
|
|
34
|
+
|
|
35
|
+
| Attribute | Values | CSS Property |
|
|
36
|
+
|--------------|---------------------------------------------------------------------------------------|---------------------|
|
|
37
|
+
| `size` | `xs` `sm` `base` `lg` `xl` `2xl` `3xl` `4xl` or raw (e.g. `"1.5em"`) | `font-size` |
|
|
38
|
+
| `weight` | `thin` `light` `normal` `medium` `semibold` `bold` `extrabold` `black` | `font-weight` |
|
|
39
|
+
| `bold` | flag (presence in raw attr string) | `font-weight:700` |
|
|
40
|
+
| `italic` | flag (presence in raw attr string) | `font-style:italic` |
|
|
41
|
+
| `color` | CSS color OR token: `primary` `secondary` `muted` `danger` `success` `warning` `info` | `color` |
|
|
42
|
+
| `font` | `Georgia` `Arial` `Verdana` `Courier New` `Times New Roman` `Trebuchet MS` | `font-family` |
|
|
43
|
+
| `transform` | `upper` `lower` `capitalize` `none` | `text-transform` |
|
|
44
|
+
| `decoration` | `underline` `line-through` `none` | `text-decoration` |
|
|
45
|
+
| `spacing` | `tight` `normal` `wide` `wider` or raw (e.g. `"0.1em"`) | `letter-spacing` |
|
|
46
|
+
| `class` | Extra CSS class(es) | `class` attribute |
|
|
47
|
+
| `id` | Element ID | `id` attribute |
|
|
48
|
+
|
|
49
|
+
> **Note:** `align` (`text-align`) is intentionally excluded. `text-align` has no effect on inline `<span>` elements.
|
|
50
|
+
> Use the `[center]` shortcode for centering, or wrap content in a `[card]` / `[grid]` for other alignment needs.
|
|
51
|
+
|
|
52
|
+
### Size token map
|
|
53
|
+
|
|
54
|
+
`xs→.75rem` · `sm→.875rem` · `base→1rem` · `lg→1.125rem` · `xl→1.25rem` · `2xl→1.5rem` · `3xl→1.875rem` · `4xl→2.25rem`
|
|
55
|
+
|
|
56
|
+
Unrecognised values pass through as raw CSS (e.g. `size="2em"` → `font-size:2em`).
|
|
57
|
+
|
|
58
|
+
### Weight token map
|
|
59
|
+
|
|
60
|
+
`thin→100` · `light→300` · `normal→400` · `medium→500` · `semibold→600` · `bold→700` · `extrabold→800` · `black→900`
|
|
61
|
+
|
|
62
|
+
### Spacing token map
|
|
63
|
+
|
|
64
|
+
`tight→-0.05em` · `normal→0em` · `wide→0.05em` · `wider→0.1em`
|
|
65
|
+
|
|
66
|
+
Unrecognised values pass through as raw CSS.
|
|
67
|
+
|
|
68
|
+
### Color token map
|
|
69
|
+
|
|
70
|
+
`primary→var(--dm-color-primary)` · `secondary→var(--dm-color-secondary)` · `muted→var(--dm-text-muted)` ·
|
|
71
|
+
`danger→var(--dm-color-danger)` · `success→var(--dm-color-success)` · `warning→var(--dm-color-warning)` ·
|
|
72
|
+
`info→var(--dm-color-info)`
|
|
73
|
+
|
|
74
|
+
Unrecognised values pass through as raw CSS (hex, rgb, named CSS colours all work).
|
|
75
|
+
|
|
76
|
+
### Font family map
|
|
77
|
+
|
|
78
|
+
`Georgia→"Georgia,serif"` · `Arial→"Arial,sans-serif"` · `Verdana→"Verdana,sans-serif"` ·
|
|
79
|
+
`Courier New→"'Courier New',monospace"` · `Times New Roman→"'Times New Roman',serif"` ·
|
|
80
|
+
`Trebuchet MS→"'Trebuchet MS',sans-serif"`
|
|
81
|
+
|
|
82
|
+
### Transform map
|
|
83
|
+
|
|
84
|
+
`upper→uppercase` · `lower→lowercase` · `capitalize→capitalize` · `none→none`
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Processing Pipeline
|
|
89
|
+
|
|
90
|
+
`processTextBlocks()` is added to `server/services/markdown.js` and inserted between `[badge]` and `[button]`:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
const withBadge = processBadgeBlocks(withTable);
|
|
94
|
+
const withText = processTextBlocks(withBadge); // ← new
|
|
95
|
+
const withButton = processButtonBlocks(withText);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Implementation notes
|
|
99
|
+
|
|
100
|
+
- Uses `scrubCodeRegions` / `restore` pattern (same as all other shortcode processors) to skip fenced code blocks.
|
|
101
|
+
- **Flag detection:** `bold` and `italic` are flag attributes detected via regex on the raw attribute string - do NOT
|
|
102
|
+
use `parseShortcodeAttrs()` for these, as it only handles `key=value` pairs. Use `/\bbold\b/i.test(attrStr)` and
|
|
103
|
+
`/\bitalic\b/i.test(attrStr)`.
|
|
104
|
+
- **`bold` + `weight` precedence:** If both `bold` flag and `weight` attribute are present, `bold` wins - emit
|
|
105
|
+
`font-weight:700` and ignore `weight`.
|
|
106
|
+
- **`class` and `id` escaping:** Values from `class` and `id` attributes must be passed through `escapeAttr()` before
|
|
107
|
+
being written into the HTML output.
|
|
108
|
+
- **Inner content:** The shortcode body passes through `marked` and then `sanitize-html` downstream - no extra escaping
|
|
109
|
+
needed in the processor itself.
|
|
110
|
+
|
|
111
|
+
No changes needed to sanitize-html config - `style`, `class`, and `id` are already whitelisted via
|
|
112
|
+
`'*': ['class', 'id', 'style', 'data-*']`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Admin Insert Menu
|
|
117
|
+
|
|
118
|
+
### markdown-toolbar.js changes
|
|
119
|
+
|
|
120
|
+
1. Register a `text-style` SVG icon in `registerIcons()`.
|
|
121
|
+
2. Add `{label: 'Text', icon: 'text-style', action: 'text'}` to the Insert dropdown items array between
|
|
122
|
+
`{label: 'Tabs', ...}` and `{label: 'Timeline', ...}`.
|
|
123
|
+
3. Add `} else if (action === 'text') { ... }` inside the existing `executeAction()` function's `else if` chain - this
|
|
124
|
+
is where the modal is opened. **There is no `onText` callback and no `page-editor.js` change needed.** All
|
|
125
|
+
insert-action modals live directly inside `executeAction()` in `markdown-toolbar.js`.
|
|
126
|
+
|
|
127
|
+
### Modal: "Style Text" (size `sm`)
|
|
128
|
+
|
|
129
|
+
Opened from the `action === 'text'` branch in `executeAction()`. Controls:
|
|
130
|
+
|
|
131
|
+
| Field | Control | Notes |
|
|
132
|
+
|------------|---------------------------|--------------------------------------------------------------------------|
|
|
133
|
+
| Content | `<input type="text">` | Pre-filled with any currently selected editor text |
|
|
134
|
+
| Size | `<select>` | Blank (default) + xs/sm/base/lg/xl/2xl/3xl/4xl |
|
|
135
|
+
| Weight | `<select>` | Blank (default) + thin/light/normal/medium/semibold/bold/extrabold/black |
|
|
136
|
+
| Bold | `<input type="checkbox">` | Shorthand - disables the Weight select when checked |
|
|
137
|
+
| Italic | `<input type="checkbox">` | |
|
|
138
|
+
| Colour | `<input type="text">` | Placeholder lists token names; accepts any CSS colour |
|
|
139
|
+
| Font | `<select>` | Blank (default) + 6 web-safe fonts |
|
|
140
|
+
| Transform | `<select>` | Blank (default) + uppercase/lowercase/capitalise/none |
|
|
141
|
+
| Decoration | `<select>` | Blank (default) + underline/line-through/none |
|
|
142
|
+
| Spacing | `<select>` | Blank (default) + tight/normal/wide/wider |
|
|
143
|
+
| CSS Class | `<input type="text">` | Optional |
|
|
144
|
+
| ID | `<input type="text">` | Optional |
|
|
145
|
+
|
|
146
|
+
**Live preview:** A wrapping `<div>` containing a `<span>` that updates in real time as controls change. Styles are
|
|
147
|
+
applied directly to the inner `<span>` to faithfully represent the actual rendered element (inline context, not block).
|
|
148
|
+
|
|
149
|
+
**Insert button:** Builds the shortcode string from only non-blank/non-default values, calls
|
|
150
|
+
`insertAtCursor(ta, snippet)`, closes the modal.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Files Changed
|
|
155
|
+
|
|
156
|
+
| File | Change |
|
|
157
|
+
|------------------------------------|-------------------------------------------------------------------------------------------------------------------|
|
|
158
|
+
| `server/services/markdown.js` | Add `processTextBlocks()`, insert into pipeline between `withBadge` and `withButton` |
|
|
159
|
+
| `admin/js/lib/markdown-toolbar.js` | Register `text-style` icon, add Insert menu entry, add `action === 'text'` branch in `executeAction()` with modal |
|
|
160
|
+
| `docs/markdown-shortcodes.md` | Document new shortcode |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Notes
|
|
165
|
+
|
|
166
|
+
- `[text]` is safe to nest inside `[card]`, `[slideover]`, `[grid]`, `[hero]`, etc.
|
|
167
|
+
- No client-side JS required - output is a plain `<span>` with inline styles, works in SSR.
|
|
168
|
+
- The modal is the canonical entry point; users can also write the shortcode by hand.
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Card Builder - Design Spec
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-04-05
|
|
4
|
+
**Status:** Approved
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Enhance the page editor's card shortcode with an interactive visual builder dialog and significantly expand the `[card]`
|
|
11
|
+
shortcode to support 33 layout templates (27 Tier 1 attribute-driven + 6 Tier 2 sub-tag structured), 6 style variants,
|
|
12
|
+
and 14 gradient presets. The builder is a modal UI that generates a shortcode string and inserts it into the markdown
|
|
13
|
+
editor at the cursor position. No new API routes or database changes are required.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Files
|
|
18
|
+
|
|
19
|
+
| File | Change |
|
|
20
|
+
|----------------------------------------|----------------------------------------------------------|
|
|
21
|
+
| `admin/js/lib/card-builder.js` | **New** - self-contained builder module |
|
|
22
|
+
| `admin/js/templates/card-builder.html` | **New** - builder dialog template |
|
|
23
|
+
| `admin/js/views/page-editor.js` | **Modified** - wire `toolbar.onCard()` |
|
|
24
|
+
| `server/services/markdown.js` | **Modified** - extend `processCardBlocks` for 33 layouts |
|
|
25
|
+
| `public/css/site.css` | **Modified** - 6 variants, 14 gradients, layout CSS |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
**Approach:** Dedicated `card-builder.js` module (Option A).
|
|
32
|
+
|
|
33
|
+
**Flow:**
|
|
34
|
+
|
|
35
|
+
1. User clicks **Card** in the markdown toolbar
|
|
36
|
+
2. `toolbar.onCard()` fires → `CardBuilder.open(textarea)` called
|
|
37
|
+
3. Modal dialog opens with layout picker, style swatches, dynamic fields, live preview
|
|
38
|
+
4. User configures card visually - preview updates in real time
|
|
39
|
+
5. User clicks **Insert Card** → shortcode string inserted at cursor → modal closes
|
|
40
|
+
6. On save/preview, `processCardBlocks()` in `markdown.js` renders shortcode to HTML
|
|
41
|
+
|
|
42
|
+
The builder is completely decoupled from the editor. It receives a textarea reference on open and writes a shortcode
|
|
43
|
+
string back on insert. It has no knowledge of the editor's internal state.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Shortcode Grammar
|
|
48
|
+
|
|
49
|
+
### Universal attributes (all layouts)
|
|
50
|
+
|
|
51
|
+
| Attribute | Values | Notes |
|
|
52
|
+
|---------------|---------------------------------------------------|---------------------------------------------------------------|
|
|
53
|
+
| `layout` | 33 layout keys | Routes to correct renderer. Omit for `header-body` (default). |
|
|
54
|
+
| `title` | string | Header title where applicable |
|
|
55
|
+
| `subtitle` | string | Secondary line beneath title |
|
|
56
|
+
| `icon` | string | Domma icon name |
|
|
57
|
+
| `icon-layout` | `inline` \| `stacked` | Icon position relative to title |
|
|
58
|
+
| `variant` | `clean` `gradient` `glass` `accent` `dark` `glow` | Visual style |
|
|
59
|
+
| `gradient` | See gradient presets | Only used when `variant="gradient"` |
|
|
60
|
+
| `hover` | flag | Adds lift effect on hover |
|
|
61
|
+
| `collapsible` | `"true"` | Toggleable body via header click |
|
|
62
|
+
| `image` | URL | Image source for image-based layouts |
|
|
63
|
+
| `footer` | string | Simple text footer |
|
|
64
|
+
| `class` | string | Extra CSS classes |
|
|
65
|
+
| `id` | string | Anchor ID |
|
|
66
|
+
|
|
67
|
+
### Layout-specific attributes
|
|
68
|
+
|
|
69
|
+
| Attribute | Layouts | Purpose |
|
|
70
|
+
|----------------|---------------------------|-------------------------------------------|
|
|
71
|
+
| `value` | stat-metric | Big display value |
|
|
72
|
+
| `delta` | stat-metric | Change indicator e.g. `↑ 12.4%` |
|
|
73
|
+
| `progress` | progress-goal | Integer 0-100 for progress bar fill |
|
|
74
|
+
| `price` | pricing | Price string e.g. `£29` |
|
|
75
|
+
| `period` | pricing | Billing period label |
|
|
76
|
+
| `lang` | code-snippet | Language label for syntax highlight badge |
|
|
77
|
+
| `filename` | file-document | Display filename |
|
|
78
|
+
| `filesize` | file-document | Size label e.g. `2.4 MB` |
|
|
79
|
+
| `filetype` | file-document | Extension badge e.g. `PDF` |
|
|
80
|
+
| `rating` | rating-review | Integer 1-5 for star display |
|
|
81
|
+
| `duration` | video-media | Time label e.g. `4:32` |
|
|
82
|
+
| `address` | location-map | Address line beneath map placeholder |
|
|
83
|
+
| `step` | step-numbered | Step number |
|
|
84
|
+
| `badge` | corner-badge, badge-band | Badge label text |
|
|
85
|
+
| `tags` | avatar-profile, tag-cloud | Comma-separated pill labels |
|
|
86
|
+
| `callout-type` | callout | `info` `warn` `success` `error` |
|
|
87
|
+
|
|
88
|
+
### Sub-tags (Tier 2 layouts)
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
[before]...[/before] → before-after (left column)
|
|
92
|
+
[after]...[/after] → before-after (right column)
|
|
93
|
+
[feature]...[/feature] → pricing, feature-comparison (repeating rows)
|
|
94
|
+
[activity user="..." action="..." time="..."] → activity-feed
|
|
95
|
+
[milestone done]...[/milestone] → progress-goal
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## The 33 Layouts
|
|
101
|
+
|
|
102
|
+
### Tier 1 - Attribute-driven (27 layouts, body is plain Markdown)
|
|
103
|
+
|
|
104
|
+
| Key | Description |
|
|
105
|
+
|-------------------------|----------------------------------------------------------------------|
|
|
106
|
+
| `basic` | Body only, no header |
|
|
107
|
+
| `header-body` | Header + body (default) |
|
|
108
|
+
| `header-body-footer` | Header + body + footer |
|
|
109
|
+
| `no-header-footer` | Body + footer, no header |
|
|
110
|
+
| `icon-top` | Icon centred above title (stacked) |
|
|
111
|
+
| `icon-inline` | Icon beside title in flex row |
|
|
112
|
+
| `image-top` | Image at top, content below |
|
|
113
|
+
| `image-overlay` | Image with title overlaid via gradient scrim |
|
|
114
|
+
| `thumb-left` | Narrow image strip left, content right |
|
|
115
|
+
| `thumb-right` | Narrow image strip right, content left |
|
|
116
|
+
| `wide-left-image` | Wide image left, content right |
|
|
117
|
+
| `full-bg` | Full dark/image background card |
|
|
118
|
+
| `split-half` | Colour/image left half, dark content right half |
|
|
119
|
+
| `avatar-profile` | Circular avatar, name, role, tag pills |
|
|
120
|
+
| `stat-metric` | Large value, label, delta, progress bar |
|
|
121
|
+
| `quote-testimonial` | Quote marks, italic text, avatar attribution |
|
|
122
|
+
| `callout` | Left accent stripe + icon (info/warn/success/error) |
|
|
123
|
+
| `video-media` | Thumbnail with play button + duration badge |
|
|
124
|
+
| `location-map` | Grid map placeholder + address |
|
|
125
|
+
| `step-numbered` | Ghost large number + step badge |
|
|
126
|
+
| `corner-badge` | Badge pinned top-right, icon, centred title |
|
|
127
|
+
| `badge-band` | Gradient band with badge + icon, then content |
|
|
128
|
+
| `glass-gradient-border` | Multi-stop gradient border ring on frosted glass |
|
|
129
|
+
| `rating-review` | Stars, italic review, avatar attribution + verified |
|
|
130
|
+
| `tag-cloud` | Heading + wrapped coloured pill tags |
|
|
131
|
+
| `timeline-entry` | Date, dot, vertical line, title, text, tag |
|
|
132
|
+
| `code-snippet` | Body is raw code (no sub-tags); `lang` attribute sets language badge |
|
|
133
|
+
|
|
134
|
+
### Tier 2 - Sub-tag structured (6 layouts, body uses named sub-tags)
|
|
135
|
+
|
|
136
|
+
| Key | Sub-tags used |
|
|
137
|
+
|----------------------|------------------------------------------------------------------------|
|
|
138
|
+
| `before-after` | `[before]` / `[after]` |
|
|
139
|
+
| `pricing` | `[feature]` list |
|
|
140
|
+
| `feature-comparison` | `[feature]` with ✓/✗ values |
|
|
141
|
+
| `activity-feed` | `[activity]` items |
|
|
142
|
+
| `progress-goal` | `[milestone]` items |
|
|
143
|
+
| `file-document` | Attributes only - any body content is silently ignored by the renderer |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 6 Style Variants
|
|
148
|
+
|
|
149
|
+
| Variant | Class | Hover Effect |
|
|
150
|
+
|------------|---------------------|-----------------------------------------------|
|
|
151
|
+
| `clean` | `.dm-card-clean` | translateY(-4px) + shadow deepen |
|
|
152
|
+
| `gradient` | `.dm-card-gradient` | translateY(-5px) + violet shadow bloom |
|
|
153
|
+
| `glass` | `.dm-card-glass` | translateY(-4px) + backdrop lightens |
|
|
154
|
+
| `accent` | `.dm-card-accent` | translateY(-3px) + border deepens + shadow |
|
|
155
|
+
| `dark` | `.dm-card-dark` | translateY(-4px) + scale(1.012) + deep shadow |
|
|
156
|
+
| `glow` | `.dm-card-glow` | ring glow expands + border brightens |
|
|
157
|
+
|
|
158
|
+
Utility: `.card-hover` (opt-in lift, no variant needed), `.card-collapsible` (header toggles body with `max-height`
|
|
159
|
+
transition).
|
|
160
|
+
|
|
161
|
+
**Collapsible wiring:** When `collapsible="true"` is parsed, `processCardBlocks` adds `.card-collapsible` to the root
|
|
162
|
+
element and `data-collapsible="true"`. `site.js` delegates a click handler on `.card-collapsible .card-header` that
|
|
163
|
+
toggles `.is-collapsed` on the root. `.is-collapsed .card-body` has `max-height: 0; overflow: hidden` with a CSS
|
|
164
|
+
transition. The header receives a CSS-only chevron via `::after` that rotates on `.is-collapsed`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 14 Gradient Presets
|
|
169
|
+
|
|
170
|
+
Applied via `gradient="name"` when `variant="gradient"`. Also controls the coloured element in `badge-band` (the top
|
|
171
|
+
band), `pricing` (the header), `step-numbered` (the background strip), and `split-half` (the left half) - all Tier 1
|
|
172
|
+
layouts. The `gradient` attribute is ignored on all other layouts.
|
|
173
|
+
|
|
174
|
+
| Name | Stops |
|
|
175
|
+
|------------|---------------------------------|
|
|
176
|
+
| `indigo` | `#6366f1 → #8b5cf6` (default) |
|
|
177
|
+
| `ocean` | `#0891b2 → #2563eb` |
|
|
178
|
+
| `sunset` | `#f59e0b → #ef4444 → #ec4899` |
|
|
179
|
+
| `forest` | `#10b981 → #0d9488` |
|
|
180
|
+
| `rose` | `#fb7185 → #e11d48` |
|
|
181
|
+
| `midnight` | `#1e1b4b → #4338ca` |
|
|
182
|
+
| `aurora` | `#06b6d4 → #6366f1 → #a855f7` |
|
|
183
|
+
| `fire` | `#ef4444 → #f97316 → #fbbf24` |
|
|
184
|
+
| `lagoon` | `#06b6d4 → #0e7490` |
|
|
185
|
+
| `dusk` | `#7c3aed → #db2777` |
|
|
186
|
+
| `lime` | `#84cc16 → #10b981` |
|
|
187
|
+
| `gold` | `#f59e0b → #b45309` |
|
|
188
|
+
| `arctic` | `#bae6fd → #e0f2fe` (dark text) |
|
|
189
|
+
| `slate` | `#475569 → #1e293b` |
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Card Builder Dialog (card-builder.js)
|
|
194
|
+
|
|
195
|
+
### Structure
|
|
196
|
+
|
|
197
|
+
- **Left panel (280px):** Layout dropdown (grouped, with thumbnail previews) → Style swatches → dynamic fields (change
|
|
198
|
+
per layout) → Options row (Collapsible / Hover toggles)
|
|
199
|
+
- **Right panel (flex):** Live preview card → Shortcode output box
|
|
200
|
+
- **Footer:** Status line (layout + style) + Cancel / Insert Card buttons
|
|
201
|
+
|
|
202
|
+
### Dynamic fields per layout tier
|
|
203
|
+
|
|
204
|
+
- **All layouts:** Title, Body textarea
|
|
205
|
+
- **Icon layouts:** Icon input + Browse Icons button (opens icon picker overlay) + icon-layout toggle
|
|
206
|
+
- **Image layouts:** Image URL + Browse Media button (opens existing media modal)
|
|
207
|
+
- **Tier 2 layouts:** Structured field set appropriate to the layout (e.g., price + period fields for pricing; step
|
|
208
|
+
number for step-numbered)
|
|
209
|
+
- **Gradient variant:** Circle swatch picker (14 presets) appears below style swatches
|
|
210
|
+
- **Glass variant:** Warning note - "Glass looks best inside a coloured [hero] or [card] section."
|
|
211
|
+
|
|
212
|
+
### Icon picker
|
|
213
|
+
|
|
214
|
+
Overlay panel with search input + grid of all Domma icons. Click to select → populates icon field + closes overlay.
|
|
215
|
+
Confirm button shows selected icon name.
|
|
216
|
+
|
|
217
|
+
### Media browser
|
|
218
|
+
|
|
219
|
+
`CardBuilder` accepts an optional `onMediaBrowse` callback in its options object:
|
|
220
|
+
`CardBuilder.open(textarea, { onMediaBrowse })`. `page-editor.js` provides this callback, which opens the existing media
|
|
221
|
+
picker modal and resolves with the selected URL. This keeps `card-builder.js` decoupled from the media system.
|
|
222
|
+
|
|
223
|
+
### Live preview
|
|
224
|
+
|
|
225
|
+
The builder ships a lightweight **client-side preview renderer** (inline in `card-builder.js`). It builds DOM nodes
|
|
226
|
+
directly using `document.createElement` and the same CSS classes that `processCardBlocks` outputs (e.g. `.card`,
|
|
227
|
+
`.dm-card-gradient`, `.card-header`, `.card-body`). It does **not** call any API endpoint. For Tier 2 layouts the
|
|
228
|
+
preview renders a simplified representative structure - e.g. pricing shows a static two-feature list rather than parsing
|
|
229
|
+
`[feature]` sub-tags. This is clearly labelled in the preview panel as "Simplified preview - full render on save."
|
|
230
|
+
|
|
231
|
+
### Shortcode generator
|
|
232
|
+
|
|
233
|
+
Builds the shortcode string from current state. Displayed in the snippet box and used on Insert.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## CSS (site.css)
|
|
238
|
+
|
|
239
|
+
### New rules added
|
|
240
|
+
|
|
241
|
+
- `.dm-card-{variant}` - 6 variant base + hover rules
|
|
242
|
+
- `.card-gradient-{name}` - 14 gradient classes (used on header/band elements)
|
|
243
|
+
- `.card-layout-{key}` - structural CSS for layouts that need it (flex, grid, image sizing)
|
|
244
|
+
- `.card-img-top`, `.card-img-left`, `.card-img-right` - image containers using `background-image` + `cover`
|
|
245
|
+
- Responsive: side-image layouts stack at `480px`
|
|
246
|
+
- Dark variant + image: auto dark scrim overlay on image containers
|
|
247
|
+
|
|
248
|
+
### toolbar.onCard() integration
|
|
249
|
+
|
|
250
|
+
`markdown-toolbar.js` already exposes `toolbar.onCard(cb)` - when the Card button is clicked, it calls `cb(textarea)` if
|
|
251
|
+
registered, otherwise falls back to a dumb snippet insert. In `page-editor.js` `onMount`, after the toolbar is
|
|
252
|
+
initialised:
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
toolbar.onCard((ta) => {
|
|
256
|
+
CardBuilder.open(ta, {
|
|
257
|
+
onMediaBrowse: () => openMediaPicker(), // returns Promise<url>
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`CardBuilder.open(textarea, options)` is the sole public API of `card-builder.js`. It opens the dialog, and on Insert
|
|
263
|
+
calls:
|
|
264
|
+
|
|
265
|
+
```js
|
|
266
|
+
const snippet = buildShortcode(state);
|
|
267
|
+
const start = textarea.selectionStart;
|
|
268
|
+
textarea.value = textarea.value.slice(0, start) + snippet + textarea.value.slice(textarea.selectionEnd);
|
|
269
|
+
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
270
|
+
textarea.focus();
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Backwards compatibility
|
|
274
|
+
|
|
275
|
+
All existing shortcodes continue to work unchanged. `processCardBlocks` checks for `layout` attribute; if absent, falls
|
|
276
|
+
back to the existing rendering path.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Image handling
|
|
281
|
+
|
|
282
|
+
- All image containers use `background-image: url(...)` + `background-size: cover` + `background-position: center`
|
|
283
|
+
- Fallback when no image provided: themed gradient placeholder matching current variant
|
|
284
|
+
- Side-image layouts (`thumb-left`, `thumb-right`, `wide-left-image`, `split-half`) stack vertically at `≤480px`
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Shortcode Examples
|
|
289
|
+
|
|
290
|
+
```markdown
|
|
291
|
+
[card layout="image-top" title="Getting Started" image="/media/hero.jpg"
|
|
292
|
+
variant="gradient" gradient="ocean" hover footer="5 min read"]
|
|
293
|
+
A short description below the image.
|
|
294
|
+
[/card]
|
|
295
|
+
|
|
296
|
+
[card layout="pricing" title="Pro" price="£29" period="per month"
|
|
297
|
+
variant="gradient" gradient="indigo"]
|
|
298
|
+
[feature]Unlimited pages[/feature]
|
|
299
|
+
[feature]All plugins[/feature]
|
|
300
|
+
[feature]Priority support[/feature]
|
|
301
|
+
[/card]
|
|
302
|
+
|
|
303
|
+
[card layout="callout" callout-type="info" icon="bulb" title="Good to know"]
|
|
304
|
+
This tip will save you time.
|
|
305
|
+
[/card]
|
|
306
|
+
|
|
307
|
+
[card layout="stat-metric" title="Monthly Revenue" value="£24,980"
|
|
308
|
+
delta="↑ 12.4%" variant="clean" hover]
|
|
309
|
+
[/card]
|
|
310
|
+
|
|
311
|
+
[card layout="before-after" title="Why switch?"]
|
|
312
|
+
[before]Manual updates · No versioning · Dev dependency[/before]
|
|
313
|
+
[after]Auto deploy · Full history · Editors own it[/after]
|
|
314
|
+
[/card]
|
|
315
|
+
```
|