mnfst 0.5.231 → 0.5.233
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/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.components.js +8 -0
- package/lib/manifest.css +341 -424
- package/lib/manifest.d.ts +172 -39
- package/lib/manifest.data.js +1 -1
- package/lib/manifest.defer.js +1 -1
- package/lib/manifest.dropdowns.js +2 -0
- package/lib/manifest.edit.css +87 -150
- package/lib/manifest.edit.js +2396 -1082
- package/lib/manifest.integrity.json +10 -10
- package/lib/manifest.js +160 -25
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.rich.text.css +253 -0
- package/lib/manifest.rich.text.js +3231 -0
- package/lib/manifest.router.js +8 -0
- package/lib/manifest.sw.js +1 -1
- package/package.json +2 -1
- package/lib/manifest.text.edit.css +0 -273
- package/lib/manifest.text.edit.js +0 -2431
package/lib/manifest.router.js
CHANGED
|
@@ -484,6 +484,8 @@ function installMpaStickyLocaleLinks() {
|
|
|
484
484
|
|
|
485
485
|
const link = event.target.closest('a');
|
|
486
486
|
if (!link || link.closest('[data-manifest-skip-locale-sticky]')) return;
|
|
487
|
+
const editable = link.closest('[contenteditable]');
|
|
488
|
+
if (link.isContentEditable || (editable && editable.getAttribute('contenteditable') !== 'false')) return; // content in editable text
|
|
487
489
|
if (link.hasAttribute('download')) return;
|
|
488
490
|
|
|
489
491
|
const hrefAttr = link.getAttribute('href');
|
|
@@ -526,9 +528,15 @@ function installMpaStickyLocaleLinks() {
|
|
|
526
528
|
function interceptLinkClicks() {
|
|
527
529
|
// Use capture phase to intercept before other handlers
|
|
528
530
|
document.addEventListener('click', (event) => {
|
|
531
|
+
if (event.defaultPrevented) return; // an editor (or the page) owns this click
|
|
529
532
|
const link = event.target.closest('a');
|
|
530
533
|
if (!link) return;
|
|
531
534
|
|
|
535
|
+
// A link inside editable text (x-rich-text, x-edit page text) is content: the click
|
|
536
|
+
// places the caret, as the browser does natively, and never navigates
|
|
537
|
+
const host = link.closest('[contenteditable]');
|
|
538
|
+
if (link.isContentEditable || (host && host.getAttribute('contenteditable') !== 'false')) return;
|
|
539
|
+
|
|
532
540
|
const href = link.getAttribute('href');
|
|
533
541
|
if (!href || href.startsWith('mailto:') || href.startsWith('tel:')) return;
|
|
534
542
|
|
package/lib/manifest.sw.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
// Build stamps the published version here; unstamped (dev) falls back to the
|
|
18
18
|
// registration URL's `v`, then 'dev'.
|
|
19
|
-
const BUILD_VERSION = '0.5.
|
|
19
|
+
const BUILD_VERSION = '0.5.233';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
// Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.233",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@tailwindcss/cli": "^4.2.4",
|
|
58
58
|
"alpinejs": "^3.17.1",
|
|
59
59
|
"cssnano": "^7.1.1",
|
|
60
|
+
"entities": "4.5.0",
|
|
60
61
|
"glob": "^11.0.2",
|
|
61
62
|
"happy-dom": "^20.11.6",
|
|
62
63
|
"puppeteer": "^24.15.0",
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/* Manifest Text Edit */
|
|
2
|
-
|
|
3
|
-
@layer base, components, utilities;
|
|
4
|
-
|
|
5
|
-
/* Self-contained. The editable area is a field first — it borrows the tokens inputs
|
|
6
|
-
and textareas use, so it sits in a form without looking bolted on. Controls are
|
|
7
|
-
styled where they are, not by where they sit, because they can be anywhere. */
|
|
8
|
-
|
|
9
|
-
@layer components {
|
|
10
|
-
|
|
11
|
-
:where([data-text-edit]) {
|
|
12
|
-
position: relative;
|
|
13
|
-
overflow-y: auto;
|
|
14
|
-
max-height: var(--text-edit-max-height, none);
|
|
15
|
-
outline: none;
|
|
16
|
-
|
|
17
|
-
/* Page-level styling — set by .page controls, read back by $text.page.
|
|
18
|
-
Presentation, so it lives here rather than inside the stored markup. */
|
|
19
|
-
font-family: var(--text-edit-font, inherit);
|
|
20
|
-
font-size: var(--text-edit-size, inherit);
|
|
21
|
-
line-height: var(--text-edit-leading, inherit);
|
|
22
|
-
text-align: var(--text-edit-align, start);
|
|
23
|
-
color: var(--text-edit-color, inherit);
|
|
24
|
-
|
|
25
|
-
/* Flagged from script: :empty never matches the <br> a contenteditable
|
|
26
|
-
keeps, and the tag holding it is not predictable after a wipe. The
|
|
27
|
-
placeholder OVERLAYS the first line (it is not a line of its own), so
|
|
28
|
-
the caret sits on top of it and nothing jumps when typing starts. */
|
|
29
|
-
&[data-text-edit-empty]::before {
|
|
30
|
-
content: attr(placeholder);
|
|
31
|
-
position: absolute;
|
|
32
|
-
inset-block-start: var(--text-edit-padding, 0.75rem);
|
|
33
|
-
inset-inline: var(--text-edit-padding, 0.75rem);
|
|
34
|
-
color: var(--color-content-subtle);
|
|
35
|
-
pointer-events: none;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* A .page background applies to an unstyled area too. */
|
|
40
|
-
:where([data-text-edit].unstyle[style*="--text-edit-background"]) {
|
|
41
|
-
background: var(--text-edit-background);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/* An unstyled area has no field padding, so its placeholder hugs the line. */
|
|
45
|
-
:where([data-text-edit].unstyle)[data-text-edit-empty]::before {
|
|
46
|
-
inset-block-start: 0;
|
|
47
|
-
inset-inline: 0;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* The FIELD look. `.unstyle` drops it so an area can sit seamlessly in a
|
|
51
|
-
page — a WYSIWYG document inherits its element's own type and colours;
|
|
52
|
-
everything above (caret custody, placeholder, commands) still works. */
|
|
53
|
-
:where([data-text-edit]:not(.unstyle)) {
|
|
54
|
-
min-height: var(--text-edit-min-height, 8rem);
|
|
55
|
-
padding: var(--text-edit-padding, 0.75rem);
|
|
56
|
-
background: var(--text-edit-background, var(--color-surface-1));
|
|
57
|
-
border: 1px solid var(--color-line);
|
|
58
|
-
border-radius: var(--radius);
|
|
59
|
-
|
|
60
|
-
/* Held while the area owns the editing session — a <select> or colour
|
|
61
|
-
control takes NATIVE focus by design, and the ring must not flicker
|
|
62
|
-
off while the writer is mid-command. */
|
|
63
|
-
&:focus,
|
|
64
|
-
&[data-text-edit-focused] {
|
|
65
|
-
border-color: var(--color-content-subtle);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/* ---- Selection menu (x-text-edit-menu) ----
|
|
70
|
-
Positioned by the --text-edit-selection-* variables the plugin writes to
|
|
71
|
-
:root, so the default needs no script; restyle or reposition freely. */
|
|
72
|
-
:where([data-text-edit-menu]) {
|
|
73
|
-
position: fixed;
|
|
74
|
-
margin: 0;
|
|
75
|
-
inset: auto;
|
|
76
|
-
left: var(--text-edit-selection-center);
|
|
77
|
-
top: var(--text-edit-selection-y);
|
|
78
|
-
transform: translate(-50%, calc(-100% - 0.5rem));
|
|
79
|
-
gap: 0.25rem;
|
|
80
|
-
align-items: center;
|
|
81
|
-
padding: 0.25rem;
|
|
82
|
-
background: var(--color-surface-1);
|
|
83
|
-
border: 1px solid var(--color-line);
|
|
84
|
-
border-radius: var(--radius);
|
|
85
|
-
box-shadow: 0 8px 30px rgb(0 0 0 / 0.2);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/* display only while OPEN: an author display on the base rule would beat
|
|
89
|
-
the UA's closed-popover display:none, leaving the menu floating fixed
|
|
90
|
-
over the page before any selection exists. */
|
|
91
|
-
:where([data-text-edit-menu]:popover-open) {
|
|
92
|
-
display: flex;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/* Without the Popover API the attribute is inert and the menu would render
|
|
96
|
-
permanently fixed on the page — hide it there; the bubble is progressive
|
|
97
|
-
enhancement. (In supporting browsers a closed popover is hidden natively.) */
|
|
98
|
-
@supports not selector(:popover-open) {
|
|
99
|
-
:where([data-text-edit-menu]) {
|
|
100
|
-
display: none;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* ---- Controls ----
|
|
105
|
-
A control is marked wherever it lives, so a toolbar is optional markup and
|
|
106
|
-
never a requirement. The reset already dims [aria-disabled=true]. */
|
|
107
|
-
:where([data-text-edit-control]) {
|
|
108
|
-
&[data-text-edit-active] {
|
|
109
|
-
background: color-mix(in oklch, var(--color-content-stark) 10%, transparent);
|
|
110
|
-
color: var(--color-content-stark);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
& > svg {
|
|
114
|
-
width: 1rem;
|
|
115
|
-
height: 1rem;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/* Icon-only buttons; text buttons keep the house padding. */
|
|
120
|
-
:where(button[data-text-edit-control]:has(> svg:only-child)) {
|
|
121
|
-
padding: 0.35rem;
|
|
122
|
-
line-height: 0;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/* The reset drops pointer events on disabled elements; a click would fall
|
|
126
|
-
through and blur the area. The plugin ignores it instead. */
|
|
127
|
-
:where([data-text-edit-control][aria-disabled=true]) {
|
|
128
|
-
pointer-events: auto;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* ---- Editable content ----
|
|
132
|
-
The editor authors real block elements, so style them as elements. Deliberately
|
|
133
|
-
lighter than the .prose class, which sets a reading measure this field can't use. */
|
|
134
|
-
:where([data-text-edit]) {
|
|
135
|
-
|
|
136
|
-
& > * + * {
|
|
137
|
-
margin-block-start: 0.75em;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
& :where(h1, h2, h3, h4, h5, h6) {
|
|
141
|
-
font-weight: 600;
|
|
142
|
-
line-height: 1.25;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
& h1 { font-size: 1.6em }
|
|
146
|
-
& h2 { font-size: 1.35em }
|
|
147
|
-
& h3 { font-size: 1.15em }
|
|
148
|
-
|
|
149
|
-
& :where(ul, ol) {
|
|
150
|
-
padding-inline-start: 1.5em;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
& li {
|
|
154
|
-
list-style: revert;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
& blockquote {
|
|
158
|
-
padding-inline-start: 0.85em;
|
|
159
|
-
border-inline-start: 2px solid var(--color-line);
|
|
160
|
-
color: var(--color-content-neutral);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
& code {
|
|
164
|
-
padding: 0.1em 0.3em;
|
|
165
|
-
border-radius: 4px;
|
|
166
|
-
font-size: 0.9em;
|
|
167
|
-
background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
& pre {
|
|
171
|
-
padding: 0.75em;
|
|
172
|
-
border-radius: var(--radius);
|
|
173
|
-
overflow-x: auto;
|
|
174
|
-
background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
|
|
175
|
-
|
|
176
|
-
& code {
|
|
177
|
-
padding: 0;
|
|
178
|
-
background: none;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
& a {
|
|
183
|
-
color: var(--color-brand-content);
|
|
184
|
-
text-decoration: underline;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
& hr {
|
|
188
|
-
margin-block: 1em;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
& img {
|
|
192
|
-
max-width: 100%;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
& table {
|
|
196
|
-
width: 100%;
|
|
197
|
-
table-layout: fixed;
|
|
198
|
-
|
|
199
|
-
& :where(td, th) {
|
|
200
|
-
padding: 0.35em 0.5em;
|
|
201
|
-
border: 1px solid var(--color-line);
|
|
202
|
-
vertical-align: top;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
& th {
|
|
206
|
-
font-weight: 600;
|
|
207
|
-
text-align: start;
|
|
208
|
-
background: var(--color-surface-2);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/* A block selection across cells. The browser can only highlight text, so an
|
|
213
|
-
empty cell shows nothing — this is what makes a spreadsheet-style
|
|
214
|
-
selection visible. */
|
|
215
|
-
& :where(td, th)[data-text-edit-cell] {
|
|
216
|
-
background: color-mix(in oklch, var(--color-brand-content) 18%, transparent);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/* Borders read as grabbable only when the pointer is on one */
|
|
220
|
-
&[data-text-edit-border="x"] { cursor: col-resize }
|
|
221
|
-
&[data-text-edit-border="y"] { cursor: row-resize }
|
|
222
|
-
&[data-text-edit-resizing] { user-select: none }
|
|
223
|
-
&[data-text-edit-resizing="x"] { cursor: col-resize }
|
|
224
|
-
&[data-text-edit-resizing="y"] { cursor: row-resize }
|
|
225
|
-
|
|
226
|
-
/* Task lists — the checkbox replaces the marker */
|
|
227
|
-
& :where(ul[data-checklist]) {
|
|
228
|
-
padding-inline-start: 0.25em;
|
|
229
|
-
list-style: none;
|
|
230
|
-
|
|
231
|
-
& li {
|
|
232
|
-
display: flex;
|
|
233
|
-
align-items: baseline;
|
|
234
|
-
gap: 0.5em;
|
|
235
|
-
list-style: none;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
& :where(dt) {
|
|
240
|
-
font-weight: 600;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
& :where(dd) {
|
|
244
|
-
margin-inline-start: 1.5em;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
& :where(kbd) {
|
|
248
|
-
padding: 0.1em 0.35em;
|
|
249
|
-
border: 1px solid var(--color-line);
|
|
250
|
-
border-radius: 4px;
|
|
251
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
252
|
-
font-size: 0.85em;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
& :where(mark) {
|
|
256
|
-
background: color-mix(in oklch, var(--color-brand-content) 25%, transparent);
|
|
257
|
-
color: inherit;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
& :where(small) {
|
|
261
|
-
font-size: 0.8em;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
& :where(figcaption) {
|
|
265
|
-
font-size: 0.8em;
|
|
266
|
-
color: var(--color-content-neutral);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
& :where(abbr, dfn) {
|
|
270
|
-
text-decoration: underline dotted;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|