@ethlete/core 5.0.0-next.58 → 5.0.0-next.59
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 +7 -0
- package/fesm2022/ethlete-core.mjs +28 -15
- package/fesm2022/ethlete-core.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ethlete-core.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @ethlete/core
|
|
2
2
|
|
|
3
|
+
## 5.0.0-next.59
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- The legacy theme stylesheets carry the page's `ngCspNonce`, and `et-structured-data` no longer writes a static `style` attribute, so both pass a strict `style-src`.
|
|
8
|
+
- `markdownToHtml` renders block and table-cell alignment as an `et-rte-align-*` class instead of an inline `text-align` style, which a strict `style-src` dropped; `htmlToMarkdown` reads both.
|
|
9
|
+
|
|
3
10
|
## 5.0.0-next.58
|
|
4
11
|
|
|
5
12
|
### Minor Changes
|
|
@@ -3470,7 +3470,9 @@ const parseSeparatorAligns = (line) => parseTableRow(line).map((cell) => {
|
|
|
3470
3470
|
});
|
|
3471
3471
|
/** The GFM separator token for a column alignment. */
|
|
3472
3472
|
const separatorFor = (align) => align === 'center' ? ':---:' : align === 'right' ? '---:' : align === 'left' ? ':---' : '---';
|
|
3473
|
-
const
|
|
3473
|
+
const alignClass = (align) => (align ? ` class="et-rte-align-${align}"` : '');
|
|
3474
|
+
const alignOf = (attrs) => (/\bclass\s*=\s*["'][^"']*\bet-rte-align-([a-z]+)/i.exec(attrs)?.[1] ??
|
|
3475
|
+
/\bstyle\s*=\s*["'][^"']*text-align:\s*([a-z]+)/i.exec(attrs)?.[1])?.toLowerCase() ?? null;
|
|
3474
3476
|
/** Wraps `content` in an emphasis `marker`, hoisting boundary whitespace outside the delimiters -
|
|
3475
3477
|
* CommonMark emphasis must not face whitespace on the inside (`** fett**` doesn't parse), and
|
|
3476
3478
|
* ` ` counts as whitespace there too. Whitespace-only content stays unwrapped. */
|
|
@@ -3737,11 +3739,11 @@ const markdownToHtml = (markdown) => {
|
|
|
3737
3739
|
// Rebuild it instead of passing it through verbatim: only the alignment survives on the tag
|
|
3738
3740
|
// (no other attributes, e.g. event handlers) and the inner markup is reduced to the editor's
|
|
3739
3741
|
// own inline vocabulary.
|
|
3740
|
-
const aligned = /^<(p|h[1-6]|div)\b[^>]
|
|
3741
|
-
|
|
3742
|
+
const aligned = /^<(p|h[1-6]|div)\b([^>]*)>([\s\S]*)<\/\1>$/i.exec(trimmed);
|
|
3743
|
+
const align = aligned ? alignOf(aligned[2] ?? '') : null;
|
|
3744
|
+
if (aligned && align) {
|
|
3742
3745
|
const tag = (aligned[1] ?? 'p').toLowerCase();
|
|
3743
|
-
|
|
3744
|
-
return `<${tag} style="text-align: ${align}">${sanitizeInlineHtml(aligned[3] ?? '')}</${tag}>`;
|
|
3746
|
+
return `<${tag}${alignClass(align)}>${sanitizeInlineHtml(aligned[3] ?? '')}</${tag}>`;
|
|
3745
3747
|
}
|
|
3746
3748
|
// Heading
|
|
3747
3749
|
const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
|
|
@@ -3758,13 +3760,13 @@ const markdownToHtml = (markdown) => {
|
|
|
3758
3760
|
const aligns = parseSeparatorAligns(tableLines[1] ?? '');
|
|
3759
3761
|
const headers = parseTableRow(tableLines[0] ?? '');
|
|
3760
3762
|
const thead = `<thead><tr>${headers
|
|
3761
|
-
.map((h, i) => `<th${
|
|
3763
|
+
.map((h, i) => `<th${alignClass(aligns[i] ?? null)}>${processInline(h)}</th>`)
|
|
3762
3764
|
.join('')}</tr></thead>`;
|
|
3763
3765
|
const bodyRows = tableLines.slice(2);
|
|
3764
3766
|
const tbody = bodyRows.length > 0
|
|
3765
3767
|
? `<tbody>${bodyRows
|
|
3766
3768
|
.map((row) => `<tr>${parseTableRow(row)
|
|
3767
|
-
.map((cell, i) => `<td${
|
|
3769
|
+
.map((cell, i) => `<td${alignClass(aligns[i] ?? null)}>${processInline(cell)}</td>`)
|
|
3768
3770
|
.join('')}</tr>`)
|
|
3769
3771
|
.join('')}</tbody>`
|
|
3770
3772
|
: '';
|
|
@@ -3805,7 +3807,10 @@ const htmlToMarkdown = (html) => {
|
|
|
3805
3807
|
// inner markup stays HTML) and round-trip via a placeholder - extracted before the block passes
|
|
3806
3808
|
// below rewrite them, restored after the final tag-strip.
|
|
3807
3809
|
const alignedBlocks = [];
|
|
3808
|
-
md = md.replace(/<(p|h[1-6]|div)\b[^>]*\
|
|
3810
|
+
md = md.replace(/<(p|h[1-6]|div)\b([^>]*\b(?:style="[^"]*text-align|class="[^"]*\bet-rte-align-)[^>]*)>([\s\S]*?)<\/\1>/gi, (_, tag, attrs, inner) => {
|
|
3811
|
+
const name = tag.toLowerCase();
|
|
3812
|
+
return makePlaceholder('ALIGN', alignedBlocks.push(`<${name} style="text-align: ${alignOf(attrs)}">${inner}</${name}>`) - 1);
|
|
3813
|
+
});
|
|
3809
3814
|
// Code blocks - process before inline code
|
|
3810
3815
|
md = md.replace(/<pre[^>]*><code[^>]*class="language-([^"]+)"[^>]*>([\s\S]*?)<\/code><\/pre>/gi, (_, lang, code) => `\n\`\`\`${lang}\n${unescapeHtml(code.trim())}\n\`\`\`\n`);
|
|
3811
3816
|
md = md.replace(/<pre[^>]*><code[^>]*>([\s\S]*?)<\/code><\/pre>/gi, (_, code) => `\n\`\`\`\n${unescapeHtml(code.trim())}\n\`\`\`\n`);
|
|
@@ -3859,8 +3864,8 @@ const htmlToMarkdown = (html) => {
|
|
|
3859
3864
|
const extractCells = (row) => [...row.matchAll(/<t[hd][^>]*>([\s\S]*?)<\/t[hd]>/gi)].map((m) => stripTags((m[1] ?? '').replace(/<br\s*\/?>/gi, ' ')).trim());
|
|
3860
3865
|
// GFM alignment is per column, read from the header cells' text-align styles
|
|
3861
3866
|
const extractAligns = (row) => [...row.matchAll(/<t[hd]([^>]*)>/gi)].map((m) => {
|
|
3862
|
-
const align =
|
|
3863
|
-
return align
|
|
3867
|
+
const align = alignOf(m[1] ?? '');
|
|
3868
|
+
return align === 'left' || align === 'center' || align === 'right' ? align : null;
|
|
3864
3869
|
});
|
|
3865
3870
|
const theadMatch = tableContent.match(/<thead[^>]*>([\s\S]*?)<\/thead>/i);
|
|
3866
3871
|
const firstTrMatch = tableContent.match(/<tr[^>]*>([\s\S]*?)<\/tr>/i);
|
|
@@ -6236,7 +6241,7 @@ class StructuredDataComponent {
|
|
|
6236
6241
|
...(ngDevMode ? [{ debugName: "jsonLD" }] : /* istanbul ignore next */ []));
|
|
6237
6242
|
}
|
|
6238
6243
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StructuredDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6239
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StructuredDataComponent, isStandalone: true, selector: "et-structured-data", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "
|
|
6244
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StructuredDataComponent, isStandalone: true, selector: "et-structured-data", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"none\"", "innerHTML": "jsonLD()" } }, ngImport: i0, template: '', isInline: true, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6240
6245
|
}
|
|
6241
6246
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StructuredDataComponent, decorators: [{
|
|
6242
6247
|
type: Component,
|
|
@@ -6245,7 +6250,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
6245
6250
|
template: '',
|
|
6246
6251
|
encapsulation: ViewEncapsulation.None,
|
|
6247
6252
|
host: {
|
|
6248
|
-
style: '
|
|
6253
|
+
'[style.display]': '"none"',
|
|
6249
6254
|
'[innerHTML]': 'jsonLD()',
|
|
6250
6255
|
},
|
|
6251
6256
|
}]
|
|
@@ -9703,6 +9708,14 @@ const injectDefaultColorTheme = () => {
|
|
|
9703
9708
|
return theme;
|
|
9704
9709
|
};
|
|
9705
9710
|
|
|
9711
|
+
/** Reads the nonce where Angular's default `CSP_NONCE` does, since these run outside any injector. */
|
|
9712
|
+
const createNoncedStyle = () => {
|
|
9713
|
+
const style = document.createElement('style');
|
|
9714
|
+
const nonce = document.body?.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce');
|
|
9715
|
+
if (nonce)
|
|
9716
|
+
style.setAttribute('nonce', nonce);
|
|
9717
|
+
return style;
|
|
9718
|
+
};
|
|
9706
9719
|
/**
|
|
9707
9720
|
* @deprecated Migrate to Tailwind v4. Intent to remove in v6.
|
|
9708
9721
|
*/
|
|
@@ -9788,7 +9801,7 @@ const createRootThemeCss = (themes) => {
|
|
|
9788
9801
|
}
|
|
9789
9802
|
`;
|
|
9790
9803
|
document.getElementById('et-root-themes')?.remove();
|
|
9791
|
-
const style =
|
|
9804
|
+
const style = createNoncedStyle();
|
|
9792
9805
|
style.id = `et-root-themes`;
|
|
9793
9806
|
style.appendChild(document.createTextNode(css));
|
|
9794
9807
|
document.head.appendChild(style);
|
|
@@ -9815,7 +9828,7 @@ const createThemeStyle = (theme, isAlt) => {
|
|
|
9815
9828
|
}
|
|
9816
9829
|
`;
|
|
9817
9830
|
document.getElementById(`${classPrefix}--${cssThemeName}`)?.remove();
|
|
9818
|
-
const style =
|
|
9831
|
+
const style = createNoncedStyle();
|
|
9819
9832
|
style.id = `${classPrefix}--${cssThemeName}`;
|
|
9820
9833
|
style.appendChild(document.createTextNode(css));
|
|
9821
9834
|
document.head.appendChild(style);
|
|
@@ -10061,7 +10074,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
10061
10074
|
|
|
10062
10075
|
// Generated from package.json by tools/scripts/generate-version.js - do not edit.
|
|
10063
10076
|
/** The version of `@ethlete/core` this build was cut from. */
|
|
10064
|
-
const CORE_VERSION = '5.0.0-next.
|
|
10077
|
+
const CORE_VERSION = '5.0.0-next.59';
|
|
10065
10078
|
|
|
10066
10079
|
/**
|
|
10067
10080
|
* Generated bundle index. Do not edit.
|