@styleflow.app/flowpress-astro-core 1.0.0-beta.5 → 1.0.0-beta.6
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 +12 -1
- package/README.md +41 -3
- package/dist/astro/BaseLayout.astro +5 -1
- package/dist/astro/CompositionRenderer.astro +126 -0
- package/dist/astro/DefaultTemplate.astro +6 -1
- package/dist/astro/GutenbergRenderer.astro +62 -51
- package/dist/astro/ThemeRuntime.astro +24 -0
- package/dist/astro/blocks/CarouselBlock.astro +4 -6
- package/dist/astro/blocks/CarouselItemBlock.astro +2 -2
- package/dist/astro/blocks/ColumnBlock.astro +2 -3
- package/dist/astro/blocks/FormBlock.astro +5 -5
- package/dist/astro/blocks/GridBlock.astro +2 -2
- package/dist/astro/blocks/HeroBlock.astro +2 -3
- package/dist/astro/blocks/ImageBlock.astro +2 -3
- package/dist/astro/blocks/ListItemFallback.astro +4 -4
- package/dist/astro/blocks/NumberSpinnerBlock.astro +24 -18
- package/dist/astro/blocks/SemanticElement.astro +35 -0
- package/dist/astro/blocks/SiteLogoBlock.astro +53 -0
- package/dist/astro/blocks/TextBlock.astro +27 -23
- package/dist/astro/blocks/ThemeToggleBlock.astro +23 -0
- package/dist/astro/blocks/helpers.d.ts +7 -0
- package/dist/astro/blocks/helpers.d.ts.map +1 -1
- package/dist/astro/blocks/helpers.js +49 -36
- package/dist/astro/blocks/helpers.js.map +1 -1
- package/dist/astro/blocks/helpers.ts +61 -40
- package/dist/block-renderers.d.ts +18 -2
- package/dist/block-renderers.d.ts.map +1 -1
- package/dist/block-renderers.js.map +1 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +31 -0
- package/dist/client.js.map +1 -1
- package/dist/composition.d.ts +14 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +86 -0
- package/dist/composition.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/styleflow.d.ts +2 -0
- package/dist/styleflow.d.ts.map +1 -1
- package/dist/styleflow.js +35 -1
- package/dist/styleflow.js.map +1 -1
- package/dist/theme-runtime.d.ts +16 -0
- package/dist/theme-runtime.d.ts.map +1 -0
- package/dist/theme-runtime.js +77 -0
- package/dist/theme-runtime.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +73 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -3
|
@@ -69,8 +69,7 @@ const fetchPriority = fetchPriorityValue(attributes.fetchPriority);
|
|
|
69
69
|
---
|
|
70
70
|
|
|
71
71
|
{src ? (
|
|
72
|
-
<S
|
|
73
|
-
as="div"
|
|
72
|
+
<S.div
|
|
74
73
|
{...semanticProps(attributes, contract)}
|
|
75
74
|
{...blockHtmlAttributes(attributes)}
|
|
76
75
|
>
|
|
@@ -86,5 +85,5 @@ const fetchPriority = fetchPriorityValue(attributes.fetchPriority);
|
|
|
86
85
|
decoding={decoding}
|
|
87
86
|
fetchpriority={fetchPriority}
|
|
88
87
|
/>
|
|
89
|
-
</S>
|
|
88
|
+
</S.div>
|
|
90
89
|
) : null}
|
|
@@ -22,9 +22,9 @@ const href = flowpressLinkHref(item.uri);
|
|
|
22
22
|
/>
|
|
23
23
|
) : null}
|
|
24
24
|
{href ? (
|
|
25
|
-
<S
|
|
25
|
+
<S.a href={href}>{String(item.title ?? "")}</S.a>
|
|
26
26
|
) : (
|
|
27
|
-
<S
|
|
27
|
+
<S.span>{String(item.title ?? "")}</S.span>
|
|
28
28
|
)}
|
|
29
|
-
{item.excerpt ? <S
|
|
30
|
-
{item.priceHtml ? <S
|
|
29
|
+
{item.excerpt ? <S.p>{String(item.excerpt)}</S.p> : null}
|
|
30
|
+
{item.priceHtml ? <S.div set:html={String(item.priceHtml)} /> : null}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
semanticProps,
|
|
13
13
|
textHtmlTag
|
|
14
14
|
} from "./helpers.js";
|
|
15
|
+
import SemanticElement from "./SemanticElement.astro";
|
|
15
16
|
|
|
16
17
|
interface Props {
|
|
17
18
|
block: FlowpressBlock;
|
|
@@ -56,8 +57,7 @@ const numberTag = textHtmlTag(attributes.numberTag);
|
|
|
56
57
|
const suffixTag = textHtmlTag(attributes.suffixTag);
|
|
57
58
|
---
|
|
58
59
|
|
|
59
|
-
<S
|
|
60
|
-
as="div"
|
|
60
|
+
<S.div
|
|
61
61
|
{...semantic}
|
|
62
62
|
{...htmlAttributes}
|
|
63
63
|
data-flowpress-number-spinner
|
|
@@ -67,18 +67,22 @@ const suffixTag = textHtmlTag(attributes.suffixTag);
|
|
|
67
67
|
data-spinner-locale={locale || undefined}
|
|
68
68
|
>
|
|
69
69
|
{prefix ? (
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
<SemanticElement
|
|
71
|
+
tag={prefixTag}
|
|
72
|
+
attributes={{
|
|
73
|
+
class: "flowpress-number-spinner__segment",
|
|
74
|
+
...prefixSemantic
|
|
75
|
+
}}
|
|
74
76
|
>
|
|
75
77
|
{prefix}
|
|
76
|
-
</
|
|
78
|
+
</SemanticElement>
|
|
77
79
|
) : null}
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
<SemanticElement
|
|
81
|
+
tag={numberTag}
|
|
82
|
+
attributes={{
|
|
83
|
+
class: "flowpress-number-spinner__segment flowpress-number-spinner__number",
|
|
84
|
+
...numberSemantic
|
|
85
|
+
}}
|
|
82
86
|
>
|
|
83
87
|
<span class="flowpress-number-spinner__accessible-value">
|
|
84
88
|
{numberText}
|
|
@@ -89,17 +93,19 @@ const suffixTag = textHtmlTag(attributes.suffixTag);
|
|
|
89
93
|
>
|
|
90
94
|
{numberText}
|
|
91
95
|
</span>
|
|
92
|
-
</
|
|
96
|
+
</SemanticElement>
|
|
93
97
|
{suffix ? (
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
<SemanticElement
|
|
99
|
+
tag={suffixTag}
|
|
100
|
+
attributes={{
|
|
101
|
+
class: "flowpress-number-spinner__segment",
|
|
102
|
+
...suffixSemantic
|
|
103
|
+
}}
|
|
98
104
|
>
|
|
99
105
|
{suffix}
|
|
100
|
-
</
|
|
106
|
+
</SemanticElement>
|
|
101
107
|
) : null}
|
|
102
|
-
</S>
|
|
108
|
+
</S.div>
|
|
103
109
|
|
|
104
110
|
<script>
|
|
105
111
|
import { initializeNumberSpinners } from "../../number-spinner.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
+
|
|
4
|
+
type SemanticElementTag =
|
|
5
|
+
| "div" | "span" | "p" | "a" | "li" | "ol" | "ul" | "blockquote"
|
|
6
|
+
| "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "strong" | "em"
|
|
7
|
+
| "small" | "mark";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
tag: SemanticElementTag;
|
|
11
|
+
attributes?: Record<string, unknown>;
|
|
12
|
+
html?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { tag, attributes = {}, html } = Astro.props;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
{tag === "div" ? <S.div {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.div>
|
|
19
|
+
: tag === "span" ? <S.span {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.span>
|
|
20
|
+
: tag === "p" ? <S.p {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.p>
|
|
21
|
+
: tag === "a" ? <S.a {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.a>
|
|
22
|
+
: tag === "li" ? <S.li {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.li>
|
|
23
|
+
: tag === "ol" ? <S.ol {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.ol>
|
|
24
|
+
: tag === "ul" ? <S.ul {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.ul>
|
|
25
|
+
: tag === "blockquote" ? <S.blockquote {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.blockquote>
|
|
26
|
+
: tag === "h1" ? <S.h1 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h1>
|
|
27
|
+
: tag === "h2" ? <S.h2 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h2>
|
|
28
|
+
: tag === "h3" ? <S.h3 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h3>
|
|
29
|
+
: tag === "h4" ? <S.h4 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h4>
|
|
30
|
+
: tag === "h5" ? <S.h5 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h5>
|
|
31
|
+
: tag === "h6" ? <S.h6 {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.h6>
|
|
32
|
+
: tag === "strong" ? <S.strong {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.strong>
|
|
33
|
+
: tag === "em" ? <S.em {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.em>
|
|
34
|
+
: tag === "small" ? <S.small {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.small>
|
|
35
|
+
: <S.mark {...attributes}>{html === undefined ? <slot /> : <Fragment set:html={html} />}</S.mark>}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
+
import type { FlowpressBlockRendererProps } from "../../block-renderers.js";
|
|
4
|
+
|
|
5
|
+
type LogoImage = { url?: string; width?: number; height?: number; alt?: string };
|
|
6
|
+
type LogoData = {
|
|
7
|
+
images?: { positive?: LogoImage; negative?: LogoImage };
|
|
8
|
+
homeUrl?: string;
|
|
9
|
+
override?: "auto" | "positive" | "negative";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { block, styleflowProps, htmlProps } = Astro.props as FlowpressBlockRendererProps;
|
|
13
|
+
const data = (block.resolvedData ?? {}) as LogoData;
|
|
14
|
+
const positive = data.images?.positive ?? {};
|
|
15
|
+
const negative = data.images?.negative ?? {};
|
|
16
|
+
const homeUrl = typeof data.homeUrl === "string" && data.homeUrl ? data.homeUrl : "/";
|
|
17
|
+
const override = data.override === "positive" || data.override === "negative"
|
|
18
|
+
? data.override
|
|
19
|
+
: "auto";
|
|
20
|
+
const rootHtmlProps = {
|
|
21
|
+
...htmlProps,
|
|
22
|
+
class: ["flowpress-site-logo", htmlProps.class].filter(Boolean).join(" ")
|
|
23
|
+
};
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
{positive.url || negative.url ? (
|
|
27
|
+
<S.a
|
|
28
|
+
{...rootHtmlProps}
|
|
29
|
+
{...styleflowProps}
|
|
30
|
+
href={homeUrl}
|
|
31
|
+
data-flowpress-logo-override={override === "auto" ? undefined : override}
|
|
32
|
+
aria-label="Home"
|
|
33
|
+
>
|
|
34
|
+
{positive.url ? (
|
|
35
|
+
<img
|
|
36
|
+
class="flowpress-site-logo__image flowpress-site-logo__image--positive"
|
|
37
|
+
src={positive.url}
|
|
38
|
+
width={positive.width || undefined}
|
|
39
|
+
height={positive.height || undefined}
|
|
40
|
+
alt={positive.alt ?? ""}
|
|
41
|
+
/>
|
|
42
|
+
) : null}
|
|
43
|
+
{negative.url ? (
|
|
44
|
+
<img
|
|
45
|
+
class="flowpress-site-logo__image flowpress-site-logo__image--negative"
|
|
46
|
+
src={negative.url}
|
|
47
|
+
width={negative.width || undefined}
|
|
48
|
+
height={negative.height || undefined}
|
|
49
|
+
alt={negative.alt ?? ""}
|
|
50
|
+
/>
|
|
51
|
+
) : null}
|
|
52
|
+
</S.a>
|
|
53
|
+
) : null}
|
|
@@ -7,10 +7,12 @@ import {
|
|
|
7
7
|
preserveEmptyTextBlock,
|
|
8
8
|
preserveRichTextSpacing,
|
|
9
9
|
semanticProps,
|
|
10
|
+
textBlockSemanticDefaults,
|
|
10
11
|
textAlignmentStyle,
|
|
11
12
|
textValue,
|
|
12
13
|
unwrapCoreHtml
|
|
13
14
|
} from "./helpers.js";
|
|
15
|
+
import SemanticElement from "./SemanticElement.astro";
|
|
14
16
|
|
|
15
17
|
interface Props {
|
|
16
18
|
block: FlowpressBlock;
|
|
@@ -24,19 +26,7 @@ const attributes = block.attributes;
|
|
|
24
26
|
const heading = name === "heading" || name === "core/heading";
|
|
25
27
|
const level = Math.min(6, Math.max(1, Number(attributes.level ?? 2)));
|
|
26
28
|
const headingTag = `h${level}` as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
27
|
-
const defaults =
|
|
28
|
-
? {
|
|
29
|
-
ty: "heading",
|
|
30
|
-
v: String(attributes.v ?? attributes.variant ?? level),
|
|
31
|
-
w: String(attributes.w ?? attributes.weight ?? "strong"),
|
|
32
|
-
foreground: "primary"
|
|
33
|
-
}
|
|
34
|
-
: {
|
|
35
|
-
ty: "body",
|
|
36
|
-
v: String(attributes.v ?? (name.includes("quote") ? "lg" : "md")),
|
|
37
|
-
w: String(attributes.w ?? "default"),
|
|
38
|
-
foreground: "primary"
|
|
39
|
-
};
|
|
29
|
+
const defaults = textBlockSemanticDefaults(name, attributes, contract);
|
|
40
30
|
const semantic = semanticProps(attributes, contract, defaults);
|
|
41
31
|
const htmlAttributes = blockHtmlAttributes(attributes);
|
|
42
32
|
const alignmentStyle = textAlignmentStyle(attributes);
|
|
@@ -60,24 +50,38 @@ const listTag = Boolean(attributes.ordered) ? "ol" : "ul";
|
|
|
60
50
|
---
|
|
61
51
|
|
|
62
52
|
{heading ? (
|
|
63
|
-
<
|
|
53
|
+
<SemanticElement
|
|
54
|
+
tag={headingTag}
|
|
55
|
+
attributes={{ ...semantic, ...htmlAttributes, style: alignmentStyle }}
|
|
56
|
+
html={html}
|
|
57
|
+
/>
|
|
64
58
|
) : name === "core/list" ? (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
<SemanticElement
|
|
60
|
+
tag={listTag}
|
|
61
|
+
attributes={{ ...semantic, ...htmlAttributes, style: alignmentStyle }}
|
|
62
|
+
html={hasChildren ? undefined : html}
|
|
63
|
+
>
|
|
64
|
+
{hasChildren ? <slot /> : null}
|
|
65
|
+
</SemanticElement>
|
|
68
66
|
) : name === "core/list-item" ? (
|
|
69
|
-
<S
|
|
67
|
+
<S.li {...semantic} {...htmlAttributes} style={alignmentStyle}>
|
|
70
68
|
<span set:html={html}></span>
|
|
71
69
|
{hasChildren ? <slot /> : null}
|
|
72
|
-
</S>
|
|
70
|
+
</S.li>
|
|
73
71
|
) : name === "quote" || name === "core/quote" ? (
|
|
74
|
-
<S
|
|
72
|
+
<S.blockquote {...semantic} {...htmlAttributes} style={alignmentStyle}>
|
|
75
73
|
{hasChildren ? <slot /> : <div set:html={html}></div>}
|
|
76
74
|
{attributes.citation ? <cite>{String(attributes.citation)}</cite> : null}
|
|
77
|
-
</S>
|
|
75
|
+
</S.blockquote>
|
|
76
|
+
) : name === "core/paragraph" ? (
|
|
77
|
+
<S.p
|
|
78
|
+
{...semantic}
|
|
79
|
+
{...htmlAttributes}
|
|
80
|
+
style={alignmentStyle}
|
|
81
|
+
set:html={html}
|
|
82
|
+
/>
|
|
78
83
|
) : (
|
|
79
|
-
<S
|
|
80
|
-
as={name === "core/paragraph" ? "p" : "div"}
|
|
84
|
+
<S.div
|
|
81
85
|
{...semantic}
|
|
82
86
|
{...htmlAttributes}
|
|
83
87
|
style={alignmentStyle}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
+
import type { FlowpressBlockRendererProps } from "../../block-renderers.js";
|
|
4
|
+
|
|
5
|
+
const { block, styleflowProps, htmlProps, composition } = Astro.props as FlowpressBlockRendererProps;
|
|
6
|
+
const label = typeof block.attributes.label === "string" && block.attributes.label.trim()
|
|
7
|
+
? block.attributes.label.trim()
|
|
8
|
+
: "Change color theme";
|
|
9
|
+
const showThemeName = block.attributes.showThemeName !== false;
|
|
10
|
+
const themeName = "Theme";
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<S.button
|
|
14
|
+
{...htmlProps}
|
|
15
|
+
{...styleflowProps}
|
|
16
|
+
type="button"
|
|
17
|
+
aria-label={label}
|
|
18
|
+
data-styleflow-theme-toggle
|
|
19
|
+
>
|
|
20
|
+
<span data-styleflow-theme-label aria-hidden="true">
|
|
21
|
+
{showThemeName ? String(themeName) : "Theme"}
|
|
22
|
+
</span>
|
|
23
|
+
</S.button>
|
|
@@ -13,6 +13,13 @@ export declare function blockHtmlAttributes(attributes: Record<string, unknown>,
|
|
|
13
13
|
};
|
|
14
14
|
export declare const TEXT_HTML_TAGS: readonly ["span", "p", "h1", "h2", "h3", "h4", "h5", "h6", "strong", "em", "small", "mark"];
|
|
15
15
|
export type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Derive a variant only when Gutenberg omitted it. The selected typography
|
|
18
|
+
* type can differ from the block's native type, so a paragraph styled as a
|
|
19
|
+
* heading must not inherit the paragraph-only `md` variant.
|
|
20
|
+
*/
|
|
21
|
+
export declare function compatibleTypographyVariant(type: string, preferred: string, contract?: StyleflowContract): string;
|
|
22
|
+
export declare function textBlockSemanticDefaults(blockName: string, attributes: Record<string, unknown>, contract?: StyleflowContract): Record<string, unknown>;
|
|
16
23
|
export declare function textHtmlTag(value: unknown): TextHtmlTag;
|
|
17
24
|
export declare function semanticProps(attributes: Record<string, unknown>, contract?: StyleflowContract, defaults?: Record<string, unknown>): Record<string, unknown>;
|
|
18
25
|
/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,4BAA4B,YAAY,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBzD;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,SAAK,GACb;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBjC;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,4BAA4B,YAAY,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBzD;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,SAAK,GACb;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBjC;AAED,eAAO,MAAM,cAAc,6FAajB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAQ1D;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,MAAM,CAcR;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmBzB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAKvD;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAA0B,GACzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAWD,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAErE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB5D;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAErE;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,SAAS,GAAG,MAAM,EAC1B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,MAAM,CAAC,CAe5D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveFlowpressBlockStyleflowProps } from "../../styleflow.js";
|
|
2
2
|
import { flowpressLinkHref } from "../../links.js";
|
|
3
3
|
export const DEFAULT_SEMANTIC_PROPS = {
|
|
4
4
|
surface: "default",
|
|
@@ -36,25 +36,6 @@ export function blockHtmlAttributes(attributes, baseClass = "") {
|
|
|
36
36
|
...(className ? { class: className } : {})
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
const SEMANTIC_KEYS = [
|
|
40
|
-
"theme",
|
|
41
|
-
"tone",
|
|
42
|
-
"intensity",
|
|
43
|
-
"surface",
|
|
44
|
-
"layoutRole",
|
|
45
|
-
"density",
|
|
46
|
-
"ty",
|
|
47
|
-
"v",
|
|
48
|
-
"w",
|
|
49
|
-
"foreground",
|
|
50
|
-
"interactivePriority",
|
|
51
|
-
"noBackground",
|
|
52
|
-
"noBorder",
|
|
53
|
-
"noPadding",
|
|
54
|
-
"noGap",
|
|
55
|
-
"noRadius",
|
|
56
|
-
"noForeground"
|
|
57
|
-
];
|
|
58
39
|
export const TEXT_HTML_TAGS = [
|
|
59
40
|
"span",
|
|
60
41
|
"p",
|
|
@@ -69,6 +50,50 @@ export const TEXT_HTML_TAGS = [
|
|
|
69
50
|
"small",
|
|
70
51
|
"mark"
|
|
71
52
|
];
|
|
53
|
+
function preferredTypographyVariant(type) {
|
|
54
|
+
if (type === "heading")
|
|
55
|
+
return "2";
|
|
56
|
+
if (type === "body" || type === "label" || type === "code")
|
|
57
|
+
return "md";
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Derive a variant only when Gutenberg omitted it. The selected typography
|
|
62
|
+
* type can differ from the block's native type, so a paragraph styled as a
|
|
63
|
+
* heading must not inherit the paragraph-only `md` variant.
|
|
64
|
+
*/
|
|
65
|
+
export function compatibleTypographyVariant(type, preferred, contract) {
|
|
66
|
+
const variants = contract?.semantic.axes.typography.variantsByType[type];
|
|
67
|
+
if (!variants?.length)
|
|
68
|
+
return preferred;
|
|
69
|
+
return [
|
|
70
|
+
preferredTypographyVariant(type),
|
|
71
|
+
preferred,
|
|
72
|
+
contract?.semantic.agentPolicy.defaults.typography.ty === type
|
|
73
|
+
? contract.semantic.agentPolicy.defaults.typography.v
|
|
74
|
+
: undefined,
|
|
75
|
+
variants[0]
|
|
76
|
+
].find((candidate) => (typeof candidate === "string" && variants.includes(candidate))) ?? preferred;
|
|
77
|
+
}
|
|
78
|
+
export function textBlockSemanticDefaults(blockName, attributes, contract) {
|
|
79
|
+
const name = blockName.replace(/^sf\//, "");
|
|
80
|
+
const heading = name === "heading" || name === "core/heading";
|
|
81
|
+
const level = Math.min(6, Math.max(1, Number(attributes.level ?? 2)));
|
|
82
|
+
const defaultType = heading ? "heading" : "body";
|
|
83
|
+
const activeType = String(attributes.ty ?? defaultType);
|
|
84
|
+
const nativeVariant = heading
|
|
85
|
+
? String(level)
|
|
86
|
+
: name.includes("quote") ? "lg" : "md";
|
|
87
|
+
const authoredVariant = attributes.v ?? attributes.variant;
|
|
88
|
+
return {
|
|
89
|
+
ty: defaultType,
|
|
90
|
+
v: authoredVariant === undefined
|
|
91
|
+
? compatibleTypographyVariant(activeType, nativeVariant, contract)
|
|
92
|
+
: String(authoredVariant),
|
|
93
|
+
w: String(attributes.w ?? attributes.weight ?? (heading ? "strong" : "default")),
|
|
94
|
+
foreground: "primary"
|
|
95
|
+
};
|
|
96
|
+
}
|
|
72
97
|
export function textHtmlTag(value) {
|
|
73
98
|
const candidate = String(value ?? "span");
|
|
74
99
|
return TEXT_HTML_TAGS.includes(candidate)
|
|
@@ -76,22 +101,10 @@ export function textHtmlTag(value) {
|
|
|
76
101
|
: "span";
|
|
77
102
|
}
|
|
78
103
|
export function semanticProps(attributes, contract, defaults = DEFAULT_SEMANTIC_PROPS) {
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return resolveDynamicStyleflowProps(input, defaults, contract, {
|
|
84
|
-
strict: process.env.NODE_ENV === "production" || process.env.STYLEFLOW_STRICT === "1",
|
|
85
|
-
onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
const resolved = { ...defaults, ...input };
|
|
89
|
-
for (const key of ["tone", "intensity", "foreground"]) {
|
|
90
|
-
if (input[key] === "inherit") {
|
|
91
|
-
delete resolved[key];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return resolved;
|
|
104
|
+
return resolveFlowpressBlockStyleflowProps(attributes, contract, defaults, {
|
|
105
|
+
strict: process.env.NODE_ENV === "production" || process.env.STYLEFLOW_STRICT === "1",
|
|
106
|
+
onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)
|
|
107
|
+
});
|
|
95
108
|
}
|
|
96
109
|
const TEXT_ALIGNMENTS = new Set([
|
|
97
110
|
"left",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveDynamicStyleflowProps,\n type StyleflowContract\n} from \"../../styleflow.js\";\nimport type { FlowpressBlock } from \"../../types.js\";\nimport { flowpressLinkHref } from \"../../links.js\";\n\nexport const DEFAULT_SEMANTIC_PROPS = {\n surface: \"default\",\n layoutRole: \"stack\",\n density: \"regular\"\n};\n\nexport const DEFAULT_HERO_OBJECT_POSITION = \"50% 50%\";\n\nexport function heroObjectPosition(value: unknown): string {\n if (typeof value !== \"string\") {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n const match = value.trim().match(\n /^(\\d+(?:\\.\\d+)?|\\.\\d+)%\\s+(\\d+(?:\\.\\d+)?|\\.\\d+)%$/\n );\n if (\n !match\n || [match[1], match[2]].some((coordinate) => {\n const numeric = Number(coordinate);\n return !Number.isFinite(numeric) || numeric < 0 || numeric > 100;\n })\n ) {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n return `${match[1]}% ${match[2]}%`;\n}\n\nexport function blockHtmlAttributes(\n attributes: Record<string, unknown>,\n baseClass = \"\"\n): { id?: string; class?: string } {\n const anchor = typeof attributes.anchor === \"string\"\n ? attributes.anchor.trim()\n : \"\";\n const customClass = typeof attributes.className === \"string\"\n ? attributes.className.trim()\n : \"\";\n const className = [baseClass.trim(), customClass]\n .filter(Boolean)\n .join(\" \")\n .replace(/\\s+/g, \" \");\n\n return {\n ...(anchor ? { id: anchor } : {}),\n ...(className ? { class: className } : {})\n };\n}\n\nconst SEMANTIC_KEYS = [\n \"theme\",\n \"tone\",\n \"intensity\",\n \"surface\",\n \"layoutRole\",\n \"density\",\n \"ty\",\n \"v\",\n \"w\",\n \"foreground\",\n \"interactivePriority\",\n \"noBackground\",\n \"noBorder\",\n \"noPadding\",\n \"noGap\",\n \"noRadius\",\n \"noForeground\"\n] as const;\n\nexport const TEXT_HTML_TAGS = [\n \"span\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"strong\",\n \"em\",\n \"small\",\n \"mark\"\n] as const;\n\nexport type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];\n\nexport function textHtmlTag(value: unknown): TextHtmlTag {\n const candidate = String(value ?? \"span\");\n return TEXT_HTML_TAGS.includes(candidate as TextHtmlTag)\n ? candidate as TextHtmlTag\n : \"span\";\n}\n\nexport function semanticProps(\n attributes: Record<string, unknown>,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = DEFAULT_SEMANTIC_PROPS\n): Record<string, unknown> {\n const input = Object.fromEntries(\n SEMANTIC_KEYS\n .filter((key) => attributes[key] !== undefined)\n .map((key) => [key, attributes[key]])\n );\n if (contract) {\n return resolveDynamicStyleflowProps(input, defaults, contract, {\n strict: process.env.NODE_ENV === \"production\" || process.env.STYLEFLOW_STRICT === \"1\",\n onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)\n });\n }\n\n const resolved = { ...defaults, ...input };\n for (const key of [\"tone\", \"intensity\", \"foreground\"]) {\n if (input[key] === \"inherit\") {\n delete resolved[key];\n }\n }\n return resolved;\n}\n\nconst TEXT_ALIGNMENTS = new Set([\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\"\n]);\n\n/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */\nexport function textAlignmentStyle(\n attributes: Record<string, unknown>\n): string | undefined {\n const style = attributes.style && typeof attributes.style === \"object\"\n && !Array.isArray(attributes.style)\n ? attributes.style as Record<string, unknown>\n : {};\n const typography = style.typography && typeof style.typography === \"object\"\n && !Array.isArray(style.typography)\n ? style.typography as Record<string, unknown>\n : {};\n const candidate = typography.textAlign ?? attributes.textAlign;\n const alignment = String(candidate ?? \"\");\n return TEXT_ALIGNMENTS.has(alignment) ? `text-align: ${alignment};` : undefined;\n}\n\nexport function prefixedTextSemanticProps(\n attributes: Record<string, unknown>,\n prefix: string,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = {}\n): Record<string, unknown> {\n const attributeName = (name: string) =>\n `${prefix}${name.charAt(0).toUpperCase()}${name.slice(1)}`;\n return semanticProps({\n ty: attributes[attributeName(\"ty\")],\n v: attributes[attributeName(\"v\")],\n w: attributes[attributeName(\"w\")],\n foreground: attributes[attributeName(\"foreground\")]\n }, contract, defaults);\n}\n\nexport function objectValue(\n block: FlowpressBlock,\n key: string\n): Record<string, unknown> {\n const value = block.attributes[key];\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {};\n}\n\nexport function textValue(block: FlowpressBlock, key = \"text\"): string {\n return String(block.attributes[key] ?? \"\");\n}\n\n/**\n * Keep intentional blank lines visible across current and legacy RichText\n * serializations. Gutenberg can represent them either as repeated `<br>` tags,\n * empty paragraph elements, or literal newlines in an attribute value.\n */\nexport function preserveRichTextSpacing(html: string): string {\n const visibleEmptyBlocks = html\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(\n /<(p|div)(\\s[^>]*)?>(?:\\s| | )*<\\/\\1>/gi,\n (_match, tag: string, attributes = \"\") =>\n `<${tag}${attributes}> </${tag}>`\n );\n\n return visibleEmptyBlocks\n .split(/(<[^>]+>)/g)\n .map((part) => {\n if (part.startsWith(\"<\") || part.trim() === \"\") {\n return part;\n }\n return part.replace(/\\n(?:[ \\t]*\\n)+/g, (newlines) =>\n \"<br>\".repeat((newlines.match(/\\n/g) || []).length)\n );\n })\n .join(\"\");\n}\n\n/** Keep an empty text element at its typographic line height without visible text. */\nexport function preserveEmptyTextBlock(html: string): string {\n return html.trim() === \"\" ? \" \" : html;\n}\n\nexport function linkValue(block: FlowpressBlock, key = \"link\"): string {\n return flowpressLinkHref(block.attributes[key]);\n}\n\nexport function responsiveValues(\n attributes: Record<string, unknown>,\n prefix: \"columns\" | \"span\",\n fallback: number\n): Record<\"base\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\", number> {\n const keys = [\"base\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\"] as const;\n const result = {} as Record<(typeof keys)[number], number>;\n let inherited = fallback;\n for (const key of keys) {\n const suffix = key === \"base\"\n ? \"Base\"\n : key === \"2xl\" ? \"2xl\" : key.charAt(0).toUpperCase() + key.slice(1);\n const candidate = Number(attributes[`${prefix}${suffix}`]);\n if (Number.isInteger(candidate) && candidate >= 1 && candidate <= 12) {\n inherited = candidate;\n }\n result[key] = inherited;\n }\n return result;\n}\n\nexport function unwrapCoreHtml(html: string): string {\n const match = html.trim().match(\n /^<(p|h[1-6]|ul|ol|li|blockquote)(?:\\s[^>]*)?>([\\s\\S]*)<\\/\\1>$/\n );\n return match?.[2] ?? html;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveFlowpressBlockStyleflowProps,\n type StyleflowContract\n} from \"../../styleflow.js\";\nimport type { FlowpressBlock } from \"../../types.js\";\nimport { flowpressLinkHref } from \"../../links.js\";\n\nexport const DEFAULT_SEMANTIC_PROPS = {\n surface: \"default\",\n layoutRole: \"stack\",\n density: \"regular\"\n};\n\nexport const DEFAULT_HERO_OBJECT_POSITION = \"50% 50%\";\n\nexport function heroObjectPosition(value: unknown): string {\n if (typeof value !== \"string\") {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n const match = value.trim().match(\n /^(\\d+(?:\\.\\d+)?|\\.\\d+)%\\s+(\\d+(?:\\.\\d+)?|\\.\\d+)%$/\n );\n if (\n !match\n || [match[1], match[2]].some((coordinate) => {\n const numeric = Number(coordinate);\n return !Number.isFinite(numeric) || numeric < 0 || numeric > 100;\n })\n ) {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n return `${match[1]}% ${match[2]}%`;\n}\n\nexport function blockHtmlAttributes(\n attributes: Record<string, unknown>,\n baseClass = \"\"\n): { id?: string; class?: string } {\n const anchor = typeof attributes.anchor === \"string\"\n ? attributes.anchor.trim()\n : \"\";\n const customClass = typeof attributes.className === \"string\"\n ? attributes.className.trim()\n : \"\";\n const className = [baseClass.trim(), customClass]\n .filter(Boolean)\n .join(\" \")\n .replace(/\\s+/g, \" \");\n\n return {\n ...(anchor ? { id: anchor } : {}),\n ...(className ? { class: className } : {})\n };\n}\n\nexport const TEXT_HTML_TAGS = [\n \"span\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"strong\",\n \"em\",\n \"small\",\n \"mark\"\n] as const;\n\nexport type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];\n\nfunction preferredTypographyVariant(type: string): string | undefined {\n if (type === \"heading\") return \"2\";\n if (type === \"body\" || type === \"label\" || type === \"code\") return \"md\";\n return undefined;\n}\n\n/**\n * Derive a variant only when Gutenberg omitted it. The selected typography\n * type can differ from the block's native type, so a paragraph styled as a\n * heading must not inherit the paragraph-only `md` variant.\n */\nexport function compatibleTypographyVariant(\n type: string,\n preferred: string,\n contract?: StyleflowContract\n): string {\n const variants = contract?.semantic.axes.typography.variantsByType[type];\n if (!variants?.length) return preferred;\n\n return [\n preferredTypographyVariant(type),\n preferred,\n contract?.semantic.agentPolicy.defaults.typography.ty === type\n ? contract.semantic.agentPolicy.defaults.typography.v\n : undefined,\n variants[0]\n ].find((candidate): candidate is string => (\n typeof candidate === \"string\" && variants.includes(candidate)\n )) ?? preferred;\n}\n\nexport function textBlockSemanticDefaults(\n blockName: string,\n attributes: Record<string, unknown>,\n contract?: StyleflowContract\n): Record<string, unknown> {\n const name = blockName.replace(/^sf\\//, \"\");\n const heading = name === \"heading\" || name === \"core/heading\";\n const level = Math.min(6, Math.max(1, Number(attributes.level ?? 2)));\n const defaultType = heading ? \"heading\" : \"body\";\n const activeType = String(attributes.ty ?? defaultType);\n const nativeVariant = heading\n ? String(level)\n : name.includes(\"quote\") ? \"lg\" : \"md\";\n const authoredVariant = attributes.v ?? attributes.variant;\n\n return {\n ty: defaultType,\n v: authoredVariant === undefined\n ? compatibleTypographyVariant(activeType, nativeVariant, contract)\n : String(authoredVariant),\n w: String(attributes.w ?? attributes.weight ?? (heading ? \"strong\" : \"default\")),\n foreground: \"primary\"\n };\n}\n\nexport function textHtmlTag(value: unknown): TextHtmlTag {\n const candidate = String(value ?? \"span\");\n return TEXT_HTML_TAGS.includes(candidate as TextHtmlTag)\n ? candidate as TextHtmlTag\n : \"span\";\n}\n\nexport function semanticProps(\n attributes: Record<string, unknown>,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = DEFAULT_SEMANTIC_PROPS\n): Record<string, unknown> {\n return resolveFlowpressBlockStyleflowProps(attributes, contract, defaults, {\n strict: process.env.NODE_ENV === \"production\" || process.env.STYLEFLOW_STRICT === \"1\",\n onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)\n });\n}\n\nconst TEXT_ALIGNMENTS = new Set([\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\"\n]);\n\n/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */\nexport function textAlignmentStyle(\n attributes: Record<string, unknown>\n): string | undefined {\n const style = attributes.style && typeof attributes.style === \"object\"\n && !Array.isArray(attributes.style)\n ? attributes.style as Record<string, unknown>\n : {};\n const typography = style.typography && typeof style.typography === \"object\"\n && !Array.isArray(style.typography)\n ? style.typography as Record<string, unknown>\n : {};\n const candidate = typography.textAlign ?? attributes.textAlign;\n const alignment = String(candidate ?? \"\");\n return TEXT_ALIGNMENTS.has(alignment) ? `text-align: ${alignment};` : undefined;\n}\n\nexport function prefixedTextSemanticProps(\n attributes: Record<string, unknown>,\n prefix: string,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = {}\n): Record<string, unknown> {\n const attributeName = (name: string) =>\n `${prefix}${name.charAt(0).toUpperCase()}${name.slice(1)}`;\n return semanticProps({\n ty: attributes[attributeName(\"ty\")],\n v: attributes[attributeName(\"v\")],\n w: attributes[attributeName(\"w\")],\n foreground: attributes[attributeName(\"foreground\")]\n }, contract, defaults);\n}\n\nexport function objectValue(\n block: FlowpressBlock,\n key: string\n): Record<string, unknown> {\n const value = block.attributes[key];\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {};\n}\n\nexport function textValue(block: FlowpressBlock, key = \"text\"): string {\n return String(block.attributes[key] ?? \"\");\n}\n\n/**\n * Keep intentional blank lines visible across current and legacy RichText\n * serializations. Gutenberg can represent them either as repeated `<br>` tags,\n * empty paragraph elements, or literal newlines in an attribute value.\n */\nexport function preserveRichTextSpacing(html: string): string {\n const visibleEmptyBlocks = html\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(\n /<(p|div)(\\s[^>]*)?>(?:\\s| | )*<\\/\\1>/gi,\n (_match, tag: string, attributes = \"\") =>\n `<${tag}${attributes}> </${tag}>`\n );\n\n return visibleEmptyBlocks\n .split(/(<[^>]+>)/g)\n .map((part) => {\n if (part.startsWith(\"<\") || part.trim() === \"\") {\n return part;\n }\n return part.replace(/\\n(?:[ \\t]*\\n)+/g, (newlines) =>\n \"<br>\".repeat((newlines.match(/\\n/g) || []).length)\n );\n })\n .join(\"\");\n}\n\n/** Keep an empty text element at its typographic line height without visible text. */\nexport function preserveEmptyTextBlock(html: string): string {\n return html.trim() === \"\" ? \" \" : html;\n}\n\nexport function linkValue(block: FlowpressBlock, key = \"link\"): string {\n return flowpressLinkHref(block.attributes[key]);\n}\n\nexport function responsiveValues(\n attributes: Record<string, unknown>,\n prefix: \"columns\" | \"span\",\n fallback: number\n): Record<\"base\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\", number> {\n const keys = [\"base\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\"] as const;\n const result = {} as Record<(typeof keys)[number], number>;\n let inherited = fallback;\n for (const key of keys) {\n const suffix = key === \"base\"\n ? \"Base\"\n : key === \"2xl\" ? \"2xl\" : key.charAt(0).toUpperCase() + key.slice(1);\n const candidate = Number(attributes[`${prefix}${suffix}`]);\n if (Number.isInteger(candidate) && candidate >= 1 && candidate <= 12) {\n inherited = candidate;\n }\n result[key] = inherited;\n }\n return result;\n}\n\nexport function unwrapCoreHtml(html: string): string {\n const match = html.trim().match(\n /^<(p|h[1-6]|ul|ol|li|blockquote)(?:\\s[^>]*)?>([\\s\\S]*)<\\/\\1>$/\n );\n return match?.[2] ?? html;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
resolveFlowpressBlockStyleflowProps,
|
|
3
3
|
type StyleflowContract
|
|
4
4
|
} from "../../styleflow.js";
|
|
5
5
|
import type { FlowpressBlock } from "../../types.js";
|
|
@@ -55,26 +55,6 @@ export function blockHtmlAttributes(
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const SEMANTIC_KEYS = [
|
|
59
|
-
"theme",
|
|
60
|
-
"tone",
|
|
61
|
-
"intensity",
|
|
62
|
-
"surface",
|
|
63
|
-
"layoutRole",
|
|
64
|
-
"density",
|
|
65
|
-
"ty",
|
|
66
|
-
"v",
|
|
67
|
-
"w",
|
|
68
|
-
"foreground",
|
|
69
|
-
"interactivePriority",
|
|
70
|
-
"noBackground",
|
|
71
|
-
"noBorder",
|
|
72
|
-
"noPadding",
|
|
73
|
-
"noGap",
|
|
74
|
-
"noRadius",
|
|
75
|
-
"noForeground"
|
|
76
|
-
] as const;
|
|
77
|
-
|
|
78
58
|
export const TEXT_HTML_TAGS = [
|
|
79
59
|
"span",
|
|
80
60
|
"p",
|
|
@@ -92,6 +72,62 @@ export const TEXT_HTML_TAGS = [
|
|
|
92
72
|
|
|
93
73
|
export type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];
|
|
94
74
|
|
|
75
|
+
function preferredTypographyVariant(type: string): string | undefined {
|
|
76
|
+
if (type === "heading") return "2";
|
|
77
|
+
if (type === "body" || type === "label" || type === "code") return "md";
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Derive a variant only when Gutenberg omitted it. The selected typography
|
|
83
|
+
* type can differ from the block's native type, so a paragraph styled as a
|
|
84
|
+
* heading must not inherit the paragraph-only `md` variant.
|
|
85
|
+
*/
|
|
86
|
+
export function compatibleTypographyVariant(
|
|
87
|
+
type: string,
|
|
88
|
+
preferred: string,
|
|
89
|
+
contract?: StyleflowContract
|
|
90
|
+
): string {
|
|
91
|
+
const variants = contract?.semantic.axes.typography.variantsByType[type];
|
|
92
|
+
if (!variants?.length) return preferred;
|
|
93
|
+
|
|
94
|
+
return [
|
|
95
|
+
preferredTypographyVariant(type),
|
|
96
|
+
preferred,
|
|
97
|
+
contract?.semantic.agentPolicy.defaults.typography.ty === type
|
|
98
|
+
? contract.semantic.agentPolicy.defaults.typography.v
|
|
99
|
+
: undefined,
|
|
100
|
+
variants[0]
|
|
101
|
+
].find((candidate): candidate is string => (
|
|
102
|
+
typeof candidate === "string" && variants.includes(candidate)
|
|
103
|
+
)) ?? preferred;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function textBlockSemanticDefaults(
|
|
107
|
+
blockName: string,
|
|
108
|
+
attributes: Record<string, unknown>,
|
|
109
|
+
contract?: StyleflowContract
|
|
110
|
+
): Record<string, unknown> {
|
|
111
|
+
const name = blockName.replace(/^sf\//, "");
|
|
112
|
+
const heading = name === "heading" || name === "core/heading";
|
|
113
|
+
const level = Math.min(6, Math.max(1, Number(attributes.level ?? 2)));
|
|
114
|
+
const defaultType = heading ? "heading" : "body";
|
|
115
|
+
const activeType = String(attributes.ty ?? defaultType);
|
|
116
|
+
const nativeVariant = heading
|
|
117
|
+
? String(level)
|
|
118
|
+
: name.includes("quote") ? "lg" : "md";
|
|
119
|
+
const authoredVariant = attributes.v ?? attributes.variant;
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
ty: defaultType,
|
|
123
|
+
v: authoredVariant === undefined
|
|
124
|
+
? compatibleTypographyVariant(activeType, nativeVariant, contract)
|
|
125
|
+
: String(authoredVariant),
|
|
126
|
+
w: String(attributes.w ?? attributes.weight ?? (heading ? "strong" : "default")),
|
|
127
|
+
foreground: "primary"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
95
131
|
export function textHtmlTag(value: unknown): TextHtmlTag {
|
|
96
132
|
const candidate = String(value ?? "span");
|
|
97
133
|
return TEXT_HTML_TAGS.includes(candidate as TextHtmlTag)
|
|
@@ -104,25 +140,10 @@ export function semanticProps(
|
|
|
104
140
|
contract?: StyleflowContract,
|
|
105
141
|
defaults: Record<string, unknown> = DEFAULT_SEMANTIC_PROPS
|
|
106
142
|
): Record<string, unknown> {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
);
|
|
112
|
-
if (contract) {
|
|
113
|
-
return resolveDynamicStyleflowProps(input, defaults, contract, {
|
|
114
|
-
strict: process.env.NODE_ENV === "production" || process.env.STYLEFLOW_STRICT === "1",
|
|
115
|
-
onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const resolved = { ...defaults, ...input };
|
|
120
|
-
for (const key of ["tone", "intensity", "foreground"]) {
|
|
121
|
-
if (input[key] === "inherit") {
|
|
122
|
-
delete resolved[key];
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return resolved;
|
|
143
|
+
return resolveFlowpressBlockStyleflowProps(attributes, contract, defaults, {
|
|
144
|
+
strict: process.env.NODE_ENV === "production" || process.env.STYLEFLOW_STRICT === "1",
|
|
145
|
+
onDiagnostic: (diagnostic) => console.warn(`[${diagnostic.code}] ${diagnostic.message}`)
|
|
146
|
+
});
|
|
126
147
|
}
|
|
127
148
|
|
|
128
149
|
const TEXT_ALIGNMENTS = new Set([
|