@designcrowd/library.brand-page 5.19.1-error-html2canvas-2 → 5.19.1-error-html2canvas-3
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/src/{CreatedOnBrandCrowd-de-de-DmKe7W8L.js → CreatedOnBrandCrowd-de-de-BPP1Wtpt.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-D2EeiNep.js → CreatedOnBrandCrowd-en-us-BlfpQiIg.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-BqVwNY1D.js → CreatedOnBrandCrowd-es-es-Tldy_pIo.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-C756a27-.js → CreatedOnBrandCrowd-fr-ca-CHmb3VQE.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-C756a27-.js → CreatedOnBrandCrowd-fr-fr-CHmb3VQE.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-FNHAnZUw.js → CreatedOnBrandCrowd-pt-br-XbU3eK3Z.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-FNHAnZUw.js → CreatedOnBrandCrowd-pt-pt-XbU3eK3Z.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-8AZZFmDt.js → CreatedOnDcom-de-de-BVMFbVbI.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-DizTP32i.js → CreatedOnDcom-en-us--kaKb1kI.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-qnp9_n_A.js → CreatedOnDcom-es-es-XXVLpF2I.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-jUs352uK.js → CreatedOnDcom-fr-ca-D-7vtMZ5.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-CTxXtHyk.js → CreatedOnDcom-fr-fr-CM9oQk77.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-nQHj8P7d.js → CreatedOnDcom-pt-br-VVgu3BEa.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-DJmVYQuL.js → CreatedOnDcom-pt-pt-CWhA8Vla.js} +1 -1
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-DityivZa.js → lib-yEV1yYI5.js} +8529 -8525
- package/lib/src/metadata-builder/builders/footer-builder.js +16 -8
- package/lib/src/metadata-builder/builders/section-field-utils.d.ts +7 -0
- package/lib/src/metadata-builder/builders/section-field-utils.js +1 -1
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +3 -3
- package/package.json +1 -1
- package/src/metadata-builder/builders/footer-builder.test.ts +63 -1
- package/src/metadata-builder/builders/footer-builder.ts +30 -14
- package/src/metadata-builder/builders/section-field-utils.ts +1 -1
- package/src/metadata-builder/parsers/ai-toolcall-parser.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {} from '../../brand-page/models';
|
|
2
2
|
import { BaseMetadataBuilder, } from '../models';
|
|
3
3
|
import { FOOTER_CHECKS } from './section-rules/footer.rules';
|
|
4
|
-
import { applyDetachedStyleOverride } from './section-field-utils';
|
|
4
|
+
import { applyDetachedStyleOverride, normalizeStyleValue, } from './section-field-utils';
|
|
5
5
|
const normaliseSocialUrl = (url) => {
|
|
6
6
|
for (const prefix of ['mailto:', 'tel:']) {
|
|
7
7
|
if (url.startsWith(prefix))
|
|
@@ -89,8 +89,21 @@ const computeSocialLinks = (current, args) => {
|
|
|
89
89
|
const applyGlobalFooterChanges = (footer, args, textStyleOptions) => {
|
|
90
90
|
if (args.copyright_text !== undefined)
|
|
91
91
|
footer.copyrightText = args.copyright_text;
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// copyright_text_style is the same text-style object sections use (typography
|
|
93
|
+
// + colour). Normalise each value the way section styles are normalised
|
|
94
|
+
// (letterSpacing int→em, lineHeight snap, null→''), then detach from the
|
|
95
|
+
// global preset via the override helper so a single call resolves the preset
|
|
96
|
+
// and clears textStyleType once — see resolveGlobalPresetIntoStyle (BP-5420).
|
|
97
|
+
if (args.copyright_text_style) {
|
|
98
|
+
const updates = {};
|
|
99
|
+
for (const [key, value] of Object.entries(args.copyright_text_style)) {
|
|
100
|
+
const normalized = normalizeStyleValue(key, value);
|
|
101
|
+
if (normalized !== undefined)
|
|
102
|
+
updates[key] = normalized;
|
|
103
|
+
}
|
|
104
|
+
if (Object.keys(updates).length > 0)
|
|
105
|
+
footer.copyrightStyle = applyDetachedStyleOverride(footer.copyrightStyle, updates, textStyleOptions);
|
|
106
|
+
}
|
|
94
107
|
};
|
|
95
108
|
const applyViewportFooterChanges = (footer, overrides) => {
|
|
96
109
|
if (overrides.display_style !== undefined)
|
|
@@ -107,11 +120,6 @@ const applyViewportFooterChanges = (footer, overrides) => {
|
|
|
107
120
|
color: overrides.icon_color,
|
|
108
121
|
fill: overrides.icon_color,
|
|
109
122
|
};
|
|
110
|
-
if (overrides.copyright_text_color !== undefined)
|
|
111
|
-
footer.copyrightStyle = {
|
|
112
|
-
...footer.copyrightStyle,
|
|
113
|
-
color: overrides.copyright_text_color,
|
|
114
|
-
};
|
|
115
123
|
if (overrides.is_logo_visible !== undefined)
|
|
116
124
|
footer.isLogoVisible = overrides.is_logo_visible;
|
|
117
125
|
if (overrides.logo_image_height !== undefined)
|
|
@@ -21,6 +21,13 @@ interface ButtonLinkArgs {
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const applyButtonLink: (content: ButtonLinkContent, args: ButtonLinkArgs) => void;
|
|
23
23
|
export declare const applyScalarFields: (content: Content, args: SectionToolArguments, sectionType: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Convert AI-sent style value to the format expected by the model.
|
|
26
|
+
* - letterSpacing: unitless 0-100 → em string (e.g., 50 → '0.5em')
|
|
27
|
+
* - null → '' (explicitly clear/reset the property)
|
|
28
|
+
* - everything else passes through as-is
|
|
29
|
+
*/
|
|
30
|
+
export declare const normalizeStyleValue: (key: string, value: unknown) => unknown;
|
|
24
31
|
/**
|
|
25
32
|
* When an executor is about to mark a content-level text style "custom" by
|
|
26
33
|
* clearing `textStyleType`, the resolved preset values (font, size, spacing,
|
|
@@ -58,7 +58,7 @@ export const applyScalarFields = (content, args, sectionType) => {
|
|
|
58
58
|
* - null → '' (explicitly clear/reset the property)
|
|
59
59
|
* - everything else passes through as-is
|
|
60
60
|
*/
|
|
61
|
-
const normalizeStyleValue = (key, value) => {
|
|
61
|
+
export const normalizeStyleValue = (key, value) => {
|
|
62
62
|
if (value === null)
|
|
63
63
|
return '';
|
|
64
64
|
if (value === undefined)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AiAssistantToolCall } from '../../clients/ai-assistant-client';
|
|
2
2
|
import type { FooterDisplayStyle, HeaderDisplayStyle, NavigationDisplayType } from '../../brand-page/constants';
|
|
3
|
-
import type { SectionType } from './section-tool-arguments';
|
|
3
|
+
import type { SectionType, TextStyleArguments } from './section-tool-arguments';
|
|
4
4
|
export declare const AI_ASSISTANT_TOOL_NAMES: {
|
|
5
5
|
readonly UPDATE_TEXT: "updateText";
|
|
6
6
|
readonly UPDATE_STYLE: "updateStyle";
|
|
@@ -111,7 +111,6 @@ export interface FooterSocialLinkItem {
|
|
|
111
111
|
export interface ViewportFooterOverrides {
|
|
112
112
|
display_style?: FooterDisplayStyle;
|
|
113
113
|
background_color?: string | null;
|
|
114
|
-
copyright_text_color?: string;
|
|
115
114
|
icon_color?: string;
|
|
116
115
|
is_logo_visible?: boolean;
|
|
117
116
|
logo_image_height?: string;
|
|
@@ -119,7 +118,8 @@ export interface ViewportFooterOverrides {
|
|
|
119
118
|
}
|
|
120
119
|
export interface UpdateFooterArguments {
|
|
121
120
|
copyright_text?: string;
|
|
122
|
-
|
|
121
|
+
/** Copyright line text-style object (typography + colour) — same shape as a section's *_style. Global: applies to both viewports. */
|
|
122
|
+
copyright_text_style?: TextStyleArguments;
|
|
123
123
|
social_links?: FooterSocialLinkItem[];
|
|
124
124
|
_replace_social_links?: boolean;
|
|
125
125
|
_remove_social_link_indices?: number[];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@designcrowd/library.brand-page",
|
|
3
3
|
"description": "A collection of Maker/Designer applications",
|
|
4
|
-
"version": "5.19.1-error-html2canvas-
|
|
4
|
+
"version": "5.19.1-error-html2canvas-3",
|
|
5
5
|
"author": "Design.com Eng",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"type": "module",
|
|
@@ -57,7 +57,7 @@ describe('FooterBuilder — copyright font vs global style', () => {
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
const { model: out } = await run(
|
|
60
|
-
{
|
|
60
|
+
{ copyright_text_style: { fontFamily: 'Anton' } },
|
|
61
61
|
model,
|
|
62
62
|
);
|
|
63
63
|
|
|
@@ -73,6 +73,68 @@ describe('FooterBuilder — copyright font vs global style', () => {
|
|
|
73
73
|
expect(style.color).toBe('#2d0b3f');
|
|
74
74
|
expect(style.textAlign).toBe('center');
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
it('applies copyright font size + weight via the style object, detaches, preserves the text', async () => {
|
|
78
|
+
const model = makeModel({
|
|
79
|
+
textStyleType: 'paragraphs',
|
|
80
|
+
textAlign: 'center',
|
|
81
|
+
fontWeight: 'bold',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const { model: out } = await run(
|
|
85
|
+
{ copyright_text_style: { fontSize: '0.875em', fontWeight: 'normal' } },
|
|
86
|
+
model,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const desktop = out.pageFooterDesktop!;
|
|
90
|
+
const style = desktop.copyrightStyle as Record<string, unknown>;
|
|
91
|
+
|
|
92
|
+
expect(style.fontSize).toBe('0.875em');
|
|
93
|
+
expect(style.fontWeight).toBe('normal');
|
|
94
|
+
expect(style.textStyleType).toBeUndefined();
|
|
95
|
+
// preset values resolved in, not lost
|
|
96
|
+
expect(style.fontFamily).toBe('Inter');
|
|
97
|
+
expect(style.textAlign).toBe('center');
|
|
98
|
+
// style-only change must NOT touch the copyright text itself
|
|
99
|
+
expect(desktop.copyrightText).toBeUndefined();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('applies copyright style to both viewports', async () => {
|
|
103
|
+
const model = makeModel({ textStyleType: 'paragraphs' });
|
|
104
|
+
|
|
105
|
+
const { model: out } = await run(
|
|
106
|
+
{ copyright_text_style: { fontSize: '0.75em', fontWeight: 'normal' } },
|
|
107
|
+
model,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
for (const vp of [out.pageFooterDesktop!, out.pageFooterMobile!]) {
|
|
111
|
+
const style = vp.copyrightStyle as Record<string, unknown>;
|
|
112
|
+
|
|
113
|
+
expect(style.fontSize).toBe('0.75em');
|
|
114
|
+
expect(style.fontWeight).toBe('normal');
|
|
115
|
+
expect(style.textStyleType).toBeUndefined();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('applies copyright colour and normalises letterSpacing (int→em) via the style object', async () => {
|
|
120
|
+
const model = makeModel({ textStyleType: 'paragraphs' });
|
|
121
|
+
|
|
122
|
+
const { model: out } = await run(
|
|
123
|
+
{ copyright_text_style: { color: '#f5f5f5', letterSpacing: 50 } },
|
|
124
|
+
model,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const style = out.pageFooterDesktop!.copyrightStyle as Record<
|
|
128
|
+
string,
|
|
129
|
+
unknown
|
|
130
|
+
>;
|
|
131
|
+
|
|
132
|
+
expect(style.color).toBe('#f5f5f5');
|
|
133
|
+
// letterSpacing int 0–100 is normalised to an em string (50 → '0.5em'),
|
|
134
|
+
// exactly as section *_style values are.
|
|
135
|
+
expect(style.letterSpacing).toBe('0.5em');
|
|
136
|
+
expect(style.textStyleType).toBeUndefined();
|
|
137
|
+
});
|
|
76
138
|
});
|
|
77
139
|
|
|
78
140
|
type Link = { imageUrl: string; url: string };
|
|
@@ -13,9 +13,15 @@ import type {
|
|
|
13
13
|
FooterSocialLinkItem,
|
|
14
14
|
} from '../parsers/ai-toolcall-parser';
|
|
15
15
|
import type { Logger } from '../logger';
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
TextStyleDeclaration,
|
|
18
|
+
TextStyleOptions,
|
|
19
|
+
} from '../../brand-page/models/styles.model';
|
|
17
20
|
import { FOOTER_CHECKS } from './section-rules/footer.rules';
|
|
18
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
applyDetachedStyleOverride,
|
|
23
|
+
normalizeStyleValue,
|
|
24
|
+
} from './section-field-utils';
|
|
19
25
|
|
|
20
26
|
type FooterSocialLink = NonNullable<
|
|
21
27
|
AbstractPageFooterStyles['socialLinks']
|
|
@@ -144,12 +150,28 @@ const applyGlobalFooterChanges = (
|
|
|
144
150
|
if (args.copyright_text !== undefined)
|
|
145
151
|
footer.copyrightText = args.copyright_text;
|
|
146
152
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
// copyright_text_style is the same text-style object sections use (typography
|
|
154
|
+
// + colour). Normalise each value the way section styles are normalised
|
|
155
|
+
// (letterSpacing int→em, lineHeight snap, null→''), then detach from the
|
|
156
|
+
// global preset via the override helper so a single call resolves the preset
|
|
157
|
+
// and clears textStyleType once — see resolveGlobalPresetIntoStyle (BP-5420).
|
|
158
|
+
if (args.copyright_text_style) {
|
|
159
|
+
const updates: Partial<TextStyleDeclaration> = {};
|
|
160
|
+
|
|
161
|
+
for (const [key, value] of Object.entries(args.copyright_text_style)) {
|
|
162
|
+
const normalized = normalizeStyleValue(key, value);
|
|
163
|
+
|
|
164
|
+
if (normalized !== undefined)
|
|
165
|
+
(updates as Record<string, unknown>)[key] = normalized;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (Object.keys(updates).length > 0)
|
|
169
|
+
footer.copyrightStyle = applyDetachedStyleOverride(
|
|
170
|
+
footer.copyrightStyle,
|
|
171
|
+
updates,
|
|
172
|
+
textStyleOptions,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
153
175
|
};
|
|
154
176
|
|
|
155
177
|
const applyViewportFooterChanges = (
|
|
@@ -173,12 +195,6 @@ const applyViewportFooterChanges = (
|
|
|
173
195
|
fill: overrides.icon_color,
|
|
174
196
|
};
|
|
175
197
|
|
|
176
|
-
if (overrides.copyright_text_color !== undefined)
|
|
177
|
-
footer.copyrightStyle = {
|
|
178
|
-
...footer.copyrightStyle,
|
|
179
|
-
color: overrides.copyright_text_color,
|
|
180
|
-
};
|
|
181
|
-
|
|
182
198
|
if (overrides.is_logo_visible !== undefined)
|
|
183
199
|
footer.isLogoVisible = overrides.is_logo_visible;
|
|
184
200
|
|
|
@@ -109,7 +109,7 @@ export const applyScalarFields = (
|
|
|
109
109
|
* - null → '' (explicitly clear/reset the property)
|
|
110
110
|
* - everything else passes through as-is
|
|
111
111
|
*/
|
|
112
|
-
const normalizeStyleValue = (key: string, value: unknown): unknown => {
|
|
112
|
+
export const normalizeStyleValue = (key: string, value: unknown): unknown => {
|
|
113
113
|
if (value === null) return '';
|
|
114
114
|
|
|
115
115
|
if (value === undefined) return undefined;
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
HeaderDisplayStyle,
|
|
5
5
|
NavigationDisplayType,
|
|
6
6
|
} from '../../brand-page/constants';
|
|
7
|
-
import type { SectionType } from './section-tool-arguments';
|
|
7
|
+
import type { SectionType, TextStyleArguments } from './section-tool-arguments';
|
|
8
8
|
|
|
9
9
|
// Tool names — must match the function names generated by the AI pipeline.
|
|
10
10
|
// Text element tools use camelCase names.
|
|
@@ -215,7 +215,6 @@ export interface FooterSocialLinkItem {
|
|
|
215
215
|
export interface ViewportFooterOverrides {
|
|
216
216
|
display_style?: FooterDisplayStyle;
|
|
217
217
|
background_color?: string | null;
|
|
218
|
-
copyright_text_color?: string;
|
|
219
218
|
icon_color?: string;
|
|
220
219
|
is_logo_visible?: boolean;
|
|
221
220
|
logo_image_height?: string;
|
|
@@ -224,7 +223,8 @@ export interface ViewportFooterOverrides {
|
|
|
224
223
|
|
|
225
224
|
export interface UpdateFooterArguments {
|
|
226
225
|
copyright_text?: string;
|
|
227
|
-
|
|
226
|
+
/** Copyright line text-style object (typography + colour) — same shape as a section's *_style. Global: applies to both viewports. */
|
|
227
|
+
copyright_text_style?: TextStyleArguments;
|
|
228
228
|
social_links?: FooterSocialLinkItem[];
|
|
229
229
|
_replace_social_links?: boolean;
|
|
230
230
|
_remove_social_link_indices?: number[];
|