@glw907/cairn-cms 0.57.0 → 0.58.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 +67 -0
- package/dist/components/CairnMediaLibrary.svelte +997 -7
- package/dist/components/EditPage.svelte +1 -0
- package/dist/components/MediaHeroField.svelte +17 -8
- package/dist/components/MediaHeroField.svelte.d.ts +13 -5
- package/dist/components/admin-icons.d.ts +4 -0
- package/dist/components/admin-icons.js +4 -0
- package/dist/components/cairn-admin.css +255 -3
- package/dist/content/frontmatter.js +5 -0
- package/dist/content/media-rewrite.d.ts +65 -0
- package/dist/content/media-rewrite.js +442 -0
- package/dist/content/types.d.ts +2 -0
- package/dist/content/validate.js +4 -0
- package/dist/log/events.d.ts +1 -1
- package/dist/media/rewrite-plan.d.ts +65 -0
- package/dist/media/rewrite-plan.js +61 -0
- package/dist/render/registry.js +1 -1
- package/dist/sveltekit/cairn-admin.d.ts +5 -0
- package/dist/sveltekit/cairn-admin.js +9 -0
- package/dist/sveltekit/content-routes.d.ts +92 -2
- package/dist/sveltekit/content-routes.js +338 -4
- package/dist/sveltekit/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/lib/components/CairnMediaLibrary.svelte +997 -7
- package/src/lib/components/EditPage.svelte +1 -0
- package/src/lib/components/MediaHeroField.svelte +17 -8
- package/src/lib/components/admin-icons.ts +4 -0
- package/src/lib/content/frontmatter.ts +4 -0
- package/src/lib/content/media-rewrite.ts +555 -0
- package/src/lib/content/types.ts +2 -0
- package/src/lib/content/validate.ts +3 -0
- package/src/lib/log/events.ts +4 -1
- package/src/lib/media/rewrite-plan.ts +122 -0
- package/src/lib/render/registry.ts +1 -1
- package/src/lib/sveltekit/cairn-admin.ts +9 -0
- package/src/lib/sveltekit/content-routes.ts +451 -6
- package/src/lib/sveltekit/index.ts +2 -0
|
@@ -1572,6 +1572,7 @@ count, the Prose/Markup posture pair, the focus and typewriter toggles, and the
|
|
|
1572
1572
|
bind:this={heroFieldRefs[field.name]}
|
|
1573
1573
|
field={{ name: field.name, label: field.label }}
|
|
1574
1574
|
value={heroValue}
|
|
1575
|
+
decorative={heroValue?.decorative ?? false}
|
|
1575
1576
|
mediaLibrary={mediaLibrary}
|
|
1576
1577
|
conceptId={data.conceptId}
|
|
1577
1578
|
id={data.id}
|
|
@@ -2,14 +2,21 @@
|
|
|
2
2
|
@component
|
|
3
3
|
The hero image frontmatter field: the persistent details-panel field that sets a concept's lead
|
|
4
4
|
picture, the one image that both leads the page and becomes the social card. It edits the structured
|
|
5
|
-
value `{ src, alt, caption }` and writes it to
|
|
6
|
-
reads. cairn stays markdown-first, so this is a structured-data form field, never a
|
|
5
|
+
value `{ src, alt, caption, decorative }` and writes it to four hidden form inputs the save path's
|
|
6
|
+
decode arm reads. cairn stays markdown-first, so this is a structured-data form field, never a
|
|
7
|
+
WYSIWYG canvas.
|
|
7
8
|
|
|
8
9
|
The field renders inside the edit form (the EditPage details loop). A nested <form> would break SSR,
|
|
9
10
|
so the field carries no <form> of its own: the working inputs in the dialog (the alt input, the
|
|
10
|
-
caption input) carry no name and never submit, and the committed value rides
|
|
11
|
-
inputs (`<name>.src`, `<name>.alt`, `<name>.caption`). "Use this image" copies
|
|
12
|
-
state into those hidden inputs; the form's own Save commits them.
|
|
11
|
+
caption input) carry no name and never submit, and the committed value rides four named hidden
|
|
12
|
+
inputs (`<name>.src`, `<name>.alt`, `<name>.caption`, `<name>.decorative`). "Use this image" copies
|
|
13
|
+
the dialog's working state into those hidden inputs; the form's own Save commits them.
|
|
14
|
+
|
|
15
|
+
The decorative choice persists for the frontmatter hero because the hero value is an object with a
|
|
16
|
+
slot for it. A reload then tells a deliberately decorative hero apart from a left-blank alt, so a
|
|
17
|
+
decorative hero no longer trips the needs-alt notice. A decorative body image (``)
|
|
18
|
+
cannot persist the same choice, since markdown alt has no slot for it, so a decorative body image
|
|
19
|
+
still reads as needs-alt on reload.
|
|
13
20
|
|
|
14
21
|
At rest, when a hero is set, the field is one row at sibling weight: the resolved thumbnail, the
|
|
15
22
|
display name, an alt-status chip (Described, Needs alt, or Decorative, each a glyph plus a label,
|
|
@@ -49,7 +56,7 @@ popover's runUpload but resolves to this field, not an editor placeholder.
|
|
|
49
56
|
/** The field descriptor: the form input name base and the visible label. */
|
|
50
57
|
field: { name: string; label: string };
|
|
51
58
|
/** The initial committed value, from `data.frontmatter[field.name]`. */
|
|
52
|
-
value?: { src: string; alt: string; caption?: string };
|
|
59
|
+
value?: { src: string; alt: string; caption?: string; decorative?: boolean };
|
|
53
60
|
/** Whether the initial hero is an explicit decorative choice (an empty alt that is not debt).
|
|
54
61
|
* Defaults false; a fresh field with an empty alt reads as needs-alt. */
|
|
55
62
|
decorative?: boolean;
|
|
@@ -444,12 +451,14 @@ popover's runUpload but resolves to this field, not an editor placeholder.
|
|
|
444
451
|
</p>
|
|
445
452
|
{/if}
|
|
446
453
|
|
|
447
|
-
<!-- The committed value rides
|
|
454
|
+
<!-- The committed value rides four named hidden inputs the save path's decode arm reads. They sit
|
|
448
455
|
inside the edit form (this component renders in the detailFields loop), so they submit; the
|
|
449
|
-
dialog's working inputs carry no name and never submit.
|
|
456
|
+
dialog's working inputs carry no name and never submit. The decorative input persists the
|
|
457
|
+
explicit decorative choice so a reload tells it apart from a left-blank alt. -->
|
|
450
458
|
<input type="hidden" name="{field.name}.src" value={committedSrc} />
|
|
451
459
|
<input type="hidden" name="{field.name}.alt" value={committedAlt} />
|
|
452
460
|
<input type="hidden" name="{field.name}.caption" value={committedCaption} />
|
|
461
|
+
<input type="hidden" name="{field.name}.decorative" value={committedDecorative ? 'true' : ''} />
|
|
453
462
|
</div>
|
|
454
463
|
|
|
455
464
|
<!-- The edit dialog: a native modal (focus trap and Escape for free). It sits at the end of the
|
|
@@ -11,6 +11,7 @@ interface Props {
|
|
|
11
11
|
src: string;
|
|
12
12
|
alt: string;
|
|
13
13
|
caption?: string;
|
|
14
|
+
decorative?: boolean;
|
|
14
15
|
};
|
|
15
16
|
/** Whether the initial hero is an explicit decorative choice (an empty alt that is not debt).
|
|
16
17
|
* Defaults false; a fresh field with an empty alt reads as needs-alt. */
|
|
@@ -36,14 +37,21 @@ interface Props {
|
|
|
36
37
|
/**
|
|
37
38
|
* The hero image frontmatter field: the persistent details-panel field that sets a concept's lead
|
|
38
39
|
* picture, the one image that both leads the page and becomes the social card. It edits the structured
|
|
39
|
-
* value `{ src, alt, caption }` and writes it to
|
|
40
|
-
* reads. cairn stays markdown-first, so this is a structured-data form field, never a
|
|
40
|
+
* value `{ src, alt, caption, decorative }` and writes it to four hidden form inputs the save path's
|
|
41
|
+
* decode arm reads. cairn stays markdown-first, so this is a structured-data form field, never a
|
|
42
|
+
* WYSIWYG canvas.
|
|
41
43
|
*
|
|
42
44
|
* The field renders inside the edit form (the EditPage details loop). A nested <form> would break SSR,
|
|
43
45
|
* so the field carries no <form> of its own: the working inputs in the dialog (the alt input, the
|
|
44
|
-
* caption input) carry no name and never submit, and the committed value rides
|
|
45
|
-
* inputs (`<name>.src`, `<name>.alt`, `<name>.caption`). "Use this image" copies
|
|
46
|
-
* state into those hidden inputs; the form's own Save commits them.
|
|
46
|
+
* caption input) carry no name and never submit, and the committed value rides four named hidden
|
|
47
|
+
* inputs (`<name>.src`, `<name>.alt`, `<name>.caption`, `<name>.decorative`). "Use this image" copies
|
|
48
|
+
* the dialog's working state into those hidden inputs; the form's own Save commits them.
|
|
49
|
+
*
|
|
50
|
+
* The decorative choice persists for the frontmatter hero because the hero value is an object with a
|
|
51
|
+
* slot for it. A reload then tells a deliberately decorative hero apart from a left-blank alt, so a
|
|
52
|
+
* decorative hero no longer trips the needs-alt notice. A decorative body image (``)
|
|
53
|
+
* cannot persist the same choice, since markdown alt has no slot for it, so a decorative body image
|
|
54
|
+
* still reads as needs-alt on reload.
|
|
47
55
|
*
|
|
48
56
|
* At rest, when a hero is set, the field is one row at sibling weight: the resolved thumbnail, the
|
|
49
57
|
* display name, an alt-status chip (Described, Needs alt, or Decorative, each a glyph plus a label,
|
|
@@ -23,3 +23,7 @@ export { default as CopyIcon } from '@lucide/svelte/icons/copy';
|
|
|
23
23
|
export { default as FileTextIcon } from '@lucide/svelte/icons/file-text';
|
|
24
24
|
export { default as ClockIcon } from '@lucide/svelte/icons/clock';
|
|
25
25
|
export { default as Link2OffIcon } from '@lucide/svelte/icons/link-2-off';
|
|
26
|
+
export { default as RefreshCwIcon } from '@lucide/svelte/icons/refresh-cw';
|
|
27
|
+
export { default as GitBranchIcon } from '@lucide/svelte/icons/git-branch';
|
|
28
|
+
export { default as ArrowRightIcon } from '@lucide/svelte/icons/arrow-right';
|
|
29
|
+
export { default as MegaphoneIcon } from '@lucide/svelte/icons/megaphone';
|
|
@@ -25,3 +25,7 @@ export { default as CopyIcon } from '@lucide/svelte/icons/copy';
|
|
|
25
25
|
export { default as FileTextIcon } from '@lucide/svelte/icons/file-text';
|
|
26
26
|
export { default as ClockIcon } from '@lucide/svelte/icons/clock';
|
|
27
27
|
export { default as Link2OffIcon } from '@lucide/svelte/icons/link-2-off';
|
|
28
|
+
export { default as RefreshCwIcon } from '@lucide/svelte/icons/refresh-cw';
|
|
29
|
+
export { default as GitBranchIcon } from '@lucide/svelte/icons/git-branch';
|
|
30
|
+
export { default as ArrowRightIcon } from '@lucide/svelte/icons/arrow-right';
|
|
31
|
+
export { default as MegaphoneIcon } from '@lucide/svelte/icons/megaphone';
|
|
@@ -2030,6 +2030,120 @@
|
|
|
2030
2030
|
}
|
|
2031
2031
|
}
|
|
2032
2032
|
|
|
2033
|
+
@layer daisyui.l1.l2.l3 {
|
|
2034
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range {
|
|
2035
|
+
appearance: none !important;
|
|
2036
|
+
webkit-appearance: none !important;
|
|
2037
|
+
--range-thumb: var(--color-base-100) !important;
|
|
2038
|
+
--range-thumb-size: calc(var(--size-selector, .25rem) * 6) !important;
|
|
2039
|
+
--range-progress: currentColor !important;
|
|
2040
|
+
--range-fill: 1 !important;
|
|
2041
|
+
--range-p: .25rem !important;
|
|
2042
|
+
--range-bg: currentColor !important;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2046
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range {
|
|
2047
|
+
--range-bg: color-mix(in oklab, currentColor 10%, #0000) !important;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range {
|
|
2052
|
+
cursor: pointer !important;
|
|
2053
|
+
vertical-align: middle !important;
|
|
2054
|
+
--radius-selector-max: calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector)) !important;
|
|
2055
|
+
border-radius: calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max))) !important;
|
|
2056
|
+
width: clamp(3rem, 20rem, 100%) !important;
|
|
2057
|
+
height: var(--range-thumb-size) !important;
|
|
2058
|
+
background-color: #0000 !important;
|
|
2059
|
+
border: none !important;
|
|
2060
|
+
overflow: hidden !important;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) [dir="rtl"] .\!range {
|
|
2064
|
+
--range-dir: -1 !important;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range:focus {
|
|
2068
|
+
outline: none !important;
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range:focus-visible {
|
|
2072
|
+
outline-offset: 2px !important;
|
|
2073
|
+
outline: 2px solid !important;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-webkit-slider-runnable-track {
|
|
2077
|
+
background-color: var(--range-bg) !important;
|
|
2078
|
+
border-radius: var(--radius-selector) !important;
|
|
2079
|
+
width: 100% !important;
|
|
2080
|
+
height: calc(var(--range-thumb-size) * .5) !important;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
@media (forced-colors: active) {
|
|
2084
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-webkit-slider-runnable-track {
|
|
2085
|
+
border: 1px solid !important;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-moz-range-track {
|
|
2089
|
+
border: 1px solid !important;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-webkit-slider-thumb {
|
|
2094
|
+
box-sizing: border-box !important;
|
|
2095
|
+
border-radius: calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max))) !important;
|
|
2096
|
+
background-color: var(--range-thumb) !important;
|
|
2097
|
+
height: var(--range-thumb-size) !important;
|
|
2098
|
+
width: var(--range-thumb-size) !important;
|
|
2099
|
+
border: var(--range-p) solid !important;
|
|
2100
|
+
appearance: none !important;
|
|
2101
|
+
webkit-appearance: none !important;
|
|
2102
|
+
color: var(--range-progress) !important;
|
|
2103
|
+
box-shadow: 0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px currentColor, 0 0 0 2rem var(--range-thumb) inset, calc((var(--range-dir, 1) * -100cqw) - (var(--range-dir, 1) * var(--range-thumb-size) / 2)) 0 0 calc(100cqw * var(--range-fill)) !important;
|
|
2104
|
+
position: relative !important;
|
|
2105
|
+
top: 50% !important;
|
|
2106
|
+
transform: translateY(-50%) !important;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2110
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-webkit-slider-thumb {
|
|
2111
|
+
box-shadow: 0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000), 0 0 0 2rem var(--range-thumb) inset, calc((var(--range-dir, 1) * -100cqw) - (var(--range-dir, 1) * var(--range-thumb-size) / 2)) 0 0 calc(100cqw * var(--range-fill)) !important;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-moz-range-track {
|
|
2116
|
+
background-color: var(--range-bg) !important;
|
|
2117
|
+
border-radius: var(--radius-selector) !important;
|
|
2118
|
+
width: 100% !important;
|
|
2119
|
+
height: calc(var(--range-thumb-size) * .5) !important;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-moz-range-thumb {
|
|
2123
|
+
box-sizing: border-box !important;
|
|
2124
|
+
border-radius: calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max))) !important;
|
|
2125
|
+
height: var(--range-thumb-size) !important;
|
|
2126
|
+
width: var(--range-thumb-size) !important;
|
|
2127
|
+
border: var(--range-p) solid !important;
|
|
2128
|
+
color: var(--range-progress) !important;
|
|
2129
|
+
box-shadow: 0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px currentColor, 0 0 0 2rem var(--range-thumb) inset, calc((var(--range-dir, 1) * -100cqw) - (var(--range-dir, 1) * var(--range-thumb-size) / 2)) 0 0 calc(100cqw * var(--range-fill)) !important;
|
|
2130
|
+
background-color: currentColor !important;
|
|
2131
|
+
position: relative !important;
|
|
2132
|
+
top: 50% !important;
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2136
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range::-moz-range-thumb {
|
|
2137
|
+
box-shadow: 0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000), 0 0 0 2rem var(--range-thumb) inset, calc((var(--range-dir, 1) * -100cqw) - (var(--range-dir, 1) * var(--range-thumb-size) / 2)) 0 0 calc(100cqw * var(--range-fill)) !important;
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\!range:disabled {
|
|
2142
|
+
cursor: not-allowed !important;
|
|
2143
|
+
opacity: .3 !important;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2033
2147
|
@layer daisyui.l1.l2.l3 {
|
|
2034
2148
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .range {
|
|
2035
2149
|
appearance: none;
|
|
@@ -3250,6 +3364,10 @@
|
|
|
3250
3364
|
order: 2;
|
|
3251
3365
|
}
|
|
3252
3366
|
|
|
3367
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .col-span-3 {
|
|
3368
|
+
grid-column: span 3 / span 3;
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3253
3371
|
@layer daisyui.l1.l2.l3 {
|
|
3254
3372
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .hero {
|
|
3255
3373
|
background-position: center;
|
|
@@ -3574,6 +3692,10 @@
|
|
|
3574
3692
|
margin-top: calc(var(--spacing) * 1);
|
|
3575
3693
|
}
|
|
3576
3694
|
|
|
3695
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .mt-1\.5 {
|
|
3696
|
+
margin-top: calc(var(--spacing) * 1.5);
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3577
3699
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .mt-2 {
|
|
3578
3700
|
margin-top: calc(var(--spacing) * 2);
|
|
3579
3701
|
}
|
|
@@ -3614,6 +3736,10 @@
|
|
|
3614
3736
|
margin-right: calc(var(--spacing) * 1);
|
|
3615
3737
|
}
|
|
3616
3738
|
|
|
3739
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .mr-auto {
|
|
3740
|
+
margin-right: auto;
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3617
3743
|
@layer daisyui.l1.l2.l3 {
|
|
3618
3744
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .fieldset-legend {
|
|
3619
3745
|
color: var(--color-base-content);
|
|
@@ -3631,6 +3757,10 @@
|
|
|
3631
3757
|
margin-bottom: calc(var(--spacing) * 1);
|
|
3632
3758
|
}
|
|
3633
3759
|
|
|
3760
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .mb-1\.5 {
|
|
3761
|
+
margin-bottom: calc(var(--spacing) * 1.5);
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3634
3764
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .mb-2 {
|
|
3635
3765
|
margin-bottom: calc(var(--spacing) * 2);
|
|
3636
3766
|
}
|
|
@@ -4163,6 +4293,10 @@
|
|
|
4163
4293
|
height: .6875rem;
|
|
4164
4294
|
}
|
|
4165
4295
|
|
|
4296
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .h-\[26px\] {
|
|
4297
|
+
height: 26px;
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4166
4300
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .h-\[70vh\] {
|
|
4167
4301
|
height: 70vh;
|
|
4168
4302
|
}
|
|
@@ -4179,6 +4313,10 @@
|
|
|
4179
4313
|
max-height: calc(var(--spacing) * 44);
|
|
4180
4314
|
}
|
|
4181
4315
|
|
|
4316
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .max-h-56 {
|
|
4317
|
+
max-height: calc(var(--spacing) * 56);
|
|
4318
|
+
}
|
|
4319
|
+
|
|
4182
4320
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .max-h-72 {
|
|
4183
4321
|
max-height: calc(var(--spacing) * 72);
|
|
4184
4322
|
}
|
|
@@ -4351,6 +4489,10 @@
|
|
|
4351
4489
|
width: 19rem;
|
|
4352
4490
|
}
|
|
4353
4491
|
|
|
4492
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .w-\[26px\] {
|
|
4493
|
+
width: 26px;
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4354
4496
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .w-\[calc\(100\%-1\.5rem\)\] {
|
|
4355
4497
|
width: calc(100% - 1.5rem);
|
|
4356
4498
|
}
|
|
@@ -4553,6 +4695,10 @@
|
|
|
4553
4695
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
4554
4696
|
}
|
|
4555
4697
|
|
|
4698
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .grid-cols-\[1fr_auto_1fr\] {
|
|
4699
|
+
grid-template-columns: 1fr auto 1fr;
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4556
4702
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .grid-cols-\[auto_1fr\] {
|
|
4557
4703
|
grid-template-columns: auto 1fr;
|
|
4558
4704
|
}
|
|
@@ -4889,6 +5035,16 @@
|
|
|
4889
5035
|
border-color: var(--cairn-card-border);
|
|
4890
5036
|
}
|
|
4891
5037
|
|
|
5038
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-\[var\(--cairn-card-border\)\]\/70 {
|
|
5039
|
+
border-color: var(--cairn-card-border);
|
|
5040
|
+
}
|
|
5041
|
+
|
|
5042
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5043
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-\[var\(--cairn-card-border\)\]\/70 {
|
|
5044
|
+
border-color: color-mix(in oklab, var(--cairn-card-border) 70%, transparent);
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
|
|
4892
5048
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-\[var\(--cairn-error-border\)\] {
|
|
4893
5049
|
border-color: var(--cairn-error-border);
|
|
4894
5050
|
}
|
|
@@ -4901,6 +5057,16 @@
|
|
|
4901
5057
|
border-color: currentColor;
|
|
4902
5058
|
}
|
|
4903
5059
|
|
|
5060
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-primary\/25 {
|
|
5061
|
+
border-color: var(--color-primary);
|
|
5062
|
+
}
|
|
5063
|
+
|
|
5064
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5065
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-primary\/25 {
|
|
5066
|
+
border-color: color-mix(in oklab, var(--color-primary) 25%, transparent);
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
|
|
4904
5070
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .border-transparent {
|
|
4905
5071
|
border-color: #0000;
|
|
4906
5072
|
}
|
|
@@ -4981,6 +5147,16 @@
|
|
|
4981
5147
|
background-color: var(--cairn-error-tint);
|
|
4982
5148
|
}
|
|
4983
5149
|
|
|
5150
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-\[var\(--cairn-warning-ink\)\]\/10 {
|
|
5151
|
+
background-color: var(--cairn-warning-ink);
|
|
5152
|
+
}
|
|
5153
|
+
|
|
5154
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5155
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-\[var\(--cairn-warning-ink\)\]\/10 {
|
|
5156
|
+
background-color: color-mix(in oklab, var(--cairn-warning-ink) 10%, transparent);
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
|
|
4984
5160
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-base-100 {
|
|
4985
5161
|
background-color: var(--color-base-100);
|
|
4986
5162
|
}
|
|
@@ -5049,6 +5225,16 @@
|
|
|
5049
5225
|
}
|
|
5050
5226
|
}
|
|
5051
5227
|
|
|
5228
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-base-content\/\[0\.06\] {
|
|
5229
|
+
background-color: var(--color-base-content);
|
|
5230
|
+
}
|
|
5231
|
+
|
|
5232
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5233
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-base-content\/\[0\.06\] {
|
|
5234
|
+
background-color: color-mix(in oklab, var(--color-base-content) 6%, transparent);
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
|
|
5052
5238
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-base-content\/\[0\.07\] {
|
|
5053
5239
|
background-color: var(--color-base-content);
|
|
5054
5240
|
}
|
|
@@ -5087,6 +5273,16 @@
|
|
|
5087
5273
|
}
|
|
5088
5274
|
}
|
|
5089
5275
|
|
|
5276
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-primary\/\[0\.05\] {
|
|
5277
|
+
background-color: var(--color-primary);
|
|
5278
|
+
}
|
|
5279
|
+
|
|
5280
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5281
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-primary\/\[0\.05\] {
|
|
5282
|
+
background-color: color-mix(in oklab, var(--color-primary) 5%, transparent);
|
|
5283
|
+
}
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5090
5286
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .bg-primary\/\[0\.06\] {
|
|
5091
5287
|
background-color: var(--color-primary);
|
|
5092
5288
|
}
|
|
@@ -5244,6 +5440,10 @@
|
|
|
5244
5440
|
}
|
|
5245
5441
|
}
|
|
5246
5442
|
|
|
5443
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .px-0\.5 {
|
|
5444
|
+
padding-inline: calc(var(--spacing) * .5);
|
|
5445
|
+
}
|
|
5446
|
+
|
|
5247
5447
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .px-1 {
|
|
5248
5448
|
padding-inline: calc(var(--spacing) * 1);
|
|
5249
5449
|
}
|
|
@@ -5356,6 +5556,10 @@
|
|
|
5356
5556
|
padding-top: calc(var(--spacing) * 1);
|
|
5357
5557
|
}
|
|
5358
5558
|
|
|
5559
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .pt-2\.5 {
|
|
5560
|
+
padding-top: calc(var(--spacing) * 2.5);
|
|
5561
|
+
}
|
|
5562
|
+
|
|
5359
5563
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .pt-3 {
|
|
5360
5564
|
padding-top: calc(var(--spacing) * 3);
|
|
5361
5565
|
}
|
|
@@ -5549,6 +5753,11 @@
|
|
|
5549
5753
|
letter-spacing: .02em;
|
|
5550
5754
|
}
|
|
5551
5755
|
|
|
5756
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .tracking-\[0\.06em\] {
|
|
5757
|
+
--tw-tracking: .06em;
|
|
5758
|
+
letter-spacing: .06em;
|
|
5759
|
+
}
|
|
5760
|
+
|
|
5552
5761
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .tracking-\[0\.08em\] {
|
|
5553
5762
|
--tw-tracking: .08em;
|
|
5554
5763
|
letter-spacing: .08em;
|
|
@@ -5717,6 +5926,16 @@
|
|
|
5717
5926
|
}
|
|
5718
5927
|
}
|
|
5719
5928
|
|
|
5929
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .decoration-\[var\(--color-muted\)\]\/55 {
|
|
5930
|
+
text-decoration-color: var(--color-muted);
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5933
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
5934
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .decoration-\[var\(--color-muted\)\]\/55 {
|
|
5935
|
+
text-decoration-color: color-mix(in oklab, var(--color-muted) 55%, transparent);
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
|
|
5720
5939
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .\[text-underline-offset\:2px\], :where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .underline-offset-2 {
|
|
5721
5940
|
text-underline-offset: 2px;
|
|
5722
5941
|
}
|
|
@@ -5741,6 +5960,10 @@
|
|
|
5741
5960
|
opacity: .6;
|
|
5742
5961
|
}
|
|
5743
5962
|
|
|
5963
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .opacity-65 {
|
|
5964
|
+
opacity: .65;
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5744
5967
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .opacity-70 {
|
|
5745
5968
|
opacity: .7;
|
|
5746
5969
|
}
|
|
@@ -5749,6 +5972,10 @@
|
|
|
5749
5972
|
opacity: .8;
|
|
5750
5973
|
}
|
|
5751
5974
|
|
|
5975
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .opacity-90 {
|
|
5976
|
+
opacity: .9;
|
|
5977
|
+
}
|
|
5978
|
+
|
|
5752
5979
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .opacity-\[0\.62\] {
|
|
5753
5980
|
opacity: .62;
|
|
5754
5981
|
}
|
|
@@ -6031,9 +6258,9 @@
|
|
|
6031
6258
|
}
|
|
6032
6259
|
}
|
|
6033
6260
|
|
|
6034
|
-
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .
|
|
6035
|
-
|
|
6036
|
-
|
|
6261
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .select-all {
|
|
6262
|
+
-webkit-user-select: all;
|
|
6263
|
+
user-select: all;
|
|
6037
6264
|
}
|
|
6038
6265
|
|
|
6039
6266
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .select-none {
|
|
@@ -6055,6 +6282,19 @@
|
|
|
6055
6282
|
margin-top: calc(var(--spacing) * 0);
|
|
6056
6283
|
}
|
|
6057
6284
|
|
|
6285
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .first\:border-t-0:first-child {
|
|
6286
|
+
border-top-style: var(--tw-border-style);
|
|
6287
|
+
border-top-width: 0;
|
|
6288
|
+
}
|
|
6289
|
+
|
|
6290
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .checked\:border-\[var\(--cairn-error-ink\)\]:checked {
|
|
6291
|
+
border-color: var(--cairn-error-ink);
|
|
6292
|
+
}
|
|
6293
|
+
|
|
6294
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .checked\:bg-\[var\(--cairn-error-ink\)\]:checked {
|
|
6295
|
+
background-color: var(--cairn-error-ink);
|
|
6296
|
+
}
|
|
6297
|
+
|
|
6058
6298
|
@media (hover: hover) {
|
|
6059
6299
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .hover\:border-\[color-mix\(in_oklab\,var\(--color-primary\)_45\%\,transparent\)\]:hover {
|
|
6060
6300
|
border-color: var(--color-primary);
|
|
@@ -6181,6 +6421,18 @@
|
|
|
6181
6421
|
}
|
|
6182
6422
|
}
|
|
6183
6423
|
|
|
6424
|
+
@media (hover: hover) {
|
|
6425
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .hover\:bg-primary\/\[0\.08\]:hover {
|
|
6426
|
+
background-color: var(--color-primary);
|
|
6427
|
+
}
|
|
6428
|
+
|
|
6429
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
6430
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .hover\:bg-primary\/\[0\.08\]:hover {
|
|
6431
|
+
background-color: color-mix(in oklab, var(--color-primary) 8%, transparent);
|
|
6432
|
+
}
|
|
6433
|
+
}
|
|
6434
|
+
}
|
|
6435
|
+
|
|
6184
6436
|
@media (hover: hover) {
|
|
6185
6437
|
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .hover\:text-\[var\(--color-primary\)\]:hover {
|
|
6186
6438
|
color: var(--color-primary);
|
|
@@ -37,6 +37,11 @@ export function frontmatterFromForm(fields, form) {
|
|
|
37
37
|
const caption = String(form.get(`${field.name}.caption`) ?? '').trim();
|
|
38
38
|
if (caption !== '')
|
|
39
39
|
value.caption = caption;
|
|
40
|
+
// An explicit decorative choice persists so a reload tells it apart from a left-blank alt.
|
|
41
|
+
// The key is dropped otherwise to keep committed frontmatter minimal.
|
|
42
|
+
const decorative = String(form.get(`${field.name}.decorative`) ?? '');
|
|
43
|
+
if (decorative === 'true')
|
|
44
|
+
value.decorative = true;
|
|
40
45
|
data[field.name] = value;
|
|
41
46
|
break;
|
|
42
47
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** One repointed reference: which surface it lived on, the old token as written, and the new token. */
|
|
2
|
+
export interface RepointPlacement {
|
|
3
|
+
kind: 'body' | 'figure' | 'hero';
|
|
4
|
+
/** The old `media:` token exactly as it was written in the source. */
|
|
5
|
+
before: string;
|
|
6
|
+
/** The new asset's canonical `media:` token (the same value for every placement). */
|
|
7
|
+
after: string;
|
|
8
|
+
}
|
|
9
|
+
/** The rewritten markdown plus the per-placement diff, in document order (hero first, then body). */
|
|
10
|
+
export interface RepointResult {
|
|
11
|
+
markdown: string;
|
|
12
|
+
placements: RepointPlacement[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Rewrite every reference to `oldHash` in one entry's raw markdown to `newToken`, and return the
|
|
16
|
+
* rewritten markdown plus a per-placement diff. Only an image-field `src:` line is rewritten in the
|
|
17
|
+
* frontmatter: the image-like keys are read via gray-matter and each key's `src:` line is located
|
|
18
|
+
* structurally within its own block, so a `media:` token that merely appears in a plain-text value (a
|
|
19
|
+
* `title:` or `description:`) is left untouched, matching extractMediaRefs. Body and figure images are
|
|
20
|
+
* matched by mdast offset over the body slice. The output is byte-for-byte identical to the input
|
|
21
|
+
* apart from the replaced token substrings, so the rest of the entry (alt text, captions, the
|
|
22
|
+
* `:::figure` fences, every other frontmatter key) is preserved exactly. A non-matching hash returns
|
|
23
|
+
* the markdown unchanged with an empty placement list; a malformed `media:` reference is left
|
|
24
|
+
* untouched. Pure and node-safe.
|
|
25
|
+
*/
|
|
26
|
+
export declare function repointMediaRef(markdown: string, oldHash: string, newToken: string): RepointResult;
|
|
27
|
+
/** Which alt bucket a placement falls in: an empty alt always gets filled, a non-empty (custom) alt is
|
|
28
|
+
* reported and only overwritten on opt-in, and a decorative hero is never touched. */
|
|
29
|
+
export type AltBucket = 'will-fill' | 'customized' | 'decorative-skipped';
|
|
30
|
+
/** One placement of the target hash and what the alt-fill does to it: which surface it lives on, its
|
|
31
|
+
* bucket, the existing alt, and the alt after the transform (unchanged for a customized alt left as
|
|
32
|
+
* is and for a decorative hero). */
|
|
33
|
+
export interface AltPlacement {
|
|
34
|
+
kind: 'body' | 'figure' | 'hero';
|
|
35
|
+
bucket: AltBucket;
|
|
36
|
+
/** The existing alt, empty string when there is none. */
|
|
37
|
+
before: string;
|
|
38
|
+
/** The alt after the transform; equals `before` when nothing changed. */
|
|
39
|
+
after: string;
|
|
40
|
+
}
|
|
41
|
+
/** The alt-filled markdown plus the per-placement diff, in document order (hero first, then body). */
|
|
42
|
+
export interface AltFillResult {
|
|
43
|
+
markdown: string;
|
|
44
|
+
placements: AltPlacement[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Set the alt at each placement of `hash` in one entry's raw markdown, and return the rewritten
|
|
48
|
+
* markdown plus a per-placement diff. An empty alt is filled with `defaultAlt` (bucket will-fill). A
|
|
49
|
+
* non-empty alt is overwritten with `defaultAlt` only when `opts.overwrite` is true (bucket
|
|
50
|
+
* customized; otherwise left unchanged but still reported, so the preview can show it and offer the
|
|
51
|
+
* opt-in). A frontmatter hero with `decorative: true` is bucket decorative-skipped and never changed.
|
|
52
|
+
* A body or figure image has no decorative slot, so its empty alt is always will-fill.
|
|
53
|
+
*
|
|
54
|
+
* The output is byte-for-byte identical to the input apart from the alt text it actually changes. The
|
|
55
|
+
* hero alt is edited inside the frontmatter block by string splice (no gray-matter serialize round
|
|
56
|
+
* trip, which would reformat the YAML); the structure read uses gray-matter only to classify buckets
|
|
57
|
+
* and read the hero alt and decorative flag. A body alt is written escaped (the way insertImage
|
|
58
|
+
* escapes it) so a `]` in the alt cannot break the image; a hero alt is written as a JSON-quoted YAML
|
|
59
|
+
* scalar so a colon, a quote, or an empty value is robust. Placements read in document order (hero
|
|
60
|
+
* first, then body in source order). A non-matching hash returns the markdown unchanged with an empty
|
|
61
|
+
* placement list. Pure and node-safe.
|
|
62
|
+
*/
|
|
63
|
+
export declare function fillAltForHash(markdown: string, hash: string, defaultAlt: string, opts: {
|
|
64
|
+
overwrite: boolean;
|
|
65
|
+
}): AltFillResult;
|