@ethlete/components 1.0.0-next.35 → 1.0.0-next.36
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 +31 -0
- package/fesm2022/ethlete-components.mjs +3584 -2103
- package/fesm2022/ethlete-components.mjs.map +1 -1
- package/generators/generators.json +10 -0
- package/generators/migrate-rich-text-editor-floating-toolbar/migration.js +57 -0
- package/generators/migrate-rich-text-editor-floating-toolbar/rich-text-editor-floating-toolbar.js +28 -0
- package/generators/migrate-rich-text-editor-floating-toolbar/schema.json +26 -0
- package/generators/migrate-rich-text-editor-tools/migration.js +64 -0
- package/generators/migrate-rich-text-editor-tools/rich-text-editor-tools.js +36 -0
- package/generators/migrate-rich-text-editor-tools/schema.json +26 -0
- package/package.json +1 -1
- package/types/ethlete-components.d.ts +1039 -210
|
@@ -5,11 +5,21 @@
|
|
|
5
5
|
"schema": "./migrate-query-error-labels/schema.json",
|
|
6
6
|
"description": "Find query-error usage affected by the English-only label default and report where German must be re-opted-in"
|
|
7
7
|
},
|
|
8
|
+
"migrate-rich-text-editor-floating-toolbar": {
|
|
9
|
+
"factory": "./migrate-rich-text-editor-floating-toolbar/migration",
|
|
10
|
+
"schema": "./migrate-rich-text-editor-floating-toolbar/schema.json",
|
|
11
|
+
"description": "Find rich text editor usage that loses the selection toolbar and report where to re-opt-in"
|
|
12
|
+
},
|
|
8
13
|
"migrate-rich-text-editor-link-editor": {
|
|
9
14
|
"factory": "./migrate-rich-text-editor-link-editor/migration",
|
|
10
15
|
"schema": "./migrate-rich-text-editor-link-editor/schema.json",
|
|
11
16
|
"description": "Find rich text editor usage that loses the link editor popover and report where to re-opt-in"
|
|
12
17
|
},
|
|
18
|
+
"migrate-rich-text-editor-tools": {
|
|
19
|
+
"factory": "./migrate-rich-text-editor-tools/migration",
|
|
20
|
+
"schema": "./migrate-rich-text-editor-tools/schema.json",
|
|
21
|
+
"description": "Find rich text editor usage that loses the heading, quote, code-block and link tools and report where to re-opt-in"
|
|
22
|
+
},
|
|
13
23
|
"icons": {
|
|
14
24
|
"factory": "./icons/generator",
|
|
15
25
|
"schema": "./icons/schema.json",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { formatFiles } from '@nx/devkit';
|
|
2
|
+
import { createMigrationScope } from '../migrate-query-error-labels/migration-scope.js';
|
|
3
|
+
import { scanRichTextEditorFloatingToolbarInFile, } from './rich-text-editor-floating-toolbar.js';
|
|
4
|
+
export const RICH_TEXT_EDITOR_FLOATING_TOOLBAR_REPORT_PATH = 'rich-text-editor-floating-toolbar-migration-tasks.md';
|
|
5
|
+
const renderReport = (tasks) => [
|
|
6
|
+
'# Rich text editor selection toolbar migration tasks',
|
|
7
|
+
'',
|
|
8
|
+
'The rich text editor no longer mounts the toolbar that follows the selection. An editor that never opts',
|
|
9
|
+
'in keeps its static toolbar only — and stops bundling the overlay runtime and anchored positioning this',
|
|
10
|
+
'was the sole reason a default editor needed, worth ~15 kB gz (~22 kB with `@floating-ui/dom`).',
|
|
11
|
+
'',
|
|
12
|
+
'To keep it, add once — app-wide, or on the component/route that renders the editor:',
|
|
13
|
+
'',
|
|
14
|
+
'```ts',
|
|
15
|
+
"import { provideRichTextEditorFloatingToolbar } from '@ethlete/components';",
|
|
16
|
+
'',
|
|
17
|
+
'provideRichTextEditorFloatingToolbar();',
|
|
18
|
+
'```',
|
|
19
|
+
'',
|
|
20
|
+
'It never offered an action the static toolbar does not, and it was already suppressed on touch devices, so',
|
|
21
|
+
'leaving it out costs no functionality — if that is fine, there is nothing to do; delete this file.',
|
|
22
|
+
'',
|
|
23
|
+
...tasks.map((task) => [`## \`${task.id}\``, '', `- ${task.file}:${task.line}`, `- ${task.message}`, ''].join('\n')),
|
|
24
|
+
].join('\n');
|
|
25
|
+
export default async function migrateRichTextEditorFloatingToolbar(tree, schema) {
|
|
26
|
+
console.log('\n🔎 Scanning for rich text editor usage affected by the opt-in selection toolbar...');
|
|
27
|
+
const scope = createMigrationScope(tree, schema);
|
|
28
|
+
console.log(` Scope: ${scope.describe()}`);
|
|
29
|
+
const tasks = [];
|
|
30
|
+
let hasFloatingToolbarProvider = false;
|
|
31
|
+
scope.visit(tree, (filePath) => {
|
|
32
|
+
if (!/\.(ts|html)$/.test(filePath) || filePath.endsWith('.d.ts'))
|
|
33
|
+
return;
|
|
34
|
+
const content = tree.read(filePath, 'utf-8');
|
|
35
|
+
if (!content)
|
|
36
|
+
return;
|
|
37
|
+
const result = scanRichTextEditorFloatingToolbarInFile(filePath, content);
|
|
38
|
+
tasks.push(...result.usages);
|
|
39
|
+
hasFloatingToolbarProvider ||= result.hasFloatingToolbarProvider;
|
|
40
|
+
});
|
|
41
|
+
if (hasFloatingToolbarProvider) {
|
|
42
|
+
console.log(' ✓ Found a provideRichTextEditorFloatingToolbar call — it is already opted back in.');
|
|
43
|
+
}
|
|
44
|
+
else if (tasks.length > 0) {
|
|
45
|
+
tree.write(RICH_TEXT_EDITOR_FLOATING_TOOLBAR_REPORT_PATH, renderReport(tasks));
|
|
46
|
+
}
|
|
47
|
+
if (!schema.skipFormat) {
|
|
48
|
+
await formatFiles(tree);
|
|
49
|
+
}
|
|
50
|
+
if (!hasFloatingToolbarProvider && tasks.length > 0) {
|
|
51
|
+
console.log(`\n⚠️ ${tasks.length} site(s) use the rich text editor without the selection toolbar — see ${RICH_TEXT_EDITOR_FLOATING_TOOLBAR_REPORT_PATH}.`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log('\n✅ Nothing to do.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=migration.js.map
|
package/generators/migrate-rich-text-editor-floating-toolbar/rich-text-editor-floating-toolbar.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rich text editor no longer mounts the toolbar that follows the selection — it is an opt-in
|
|
3
|
+
* `provideRichTextEditorFloatingToolbar()`, and without it an editor keeps its static toolbar only.
|
|
4
|
+
* Whether an app wants it back is its own call, so this migration only finds the affected sites and
|
|
5
|
+
* reports them; it rewrites nothing.
|
|
6
|
+
*/
|
|
7
|
+
const USAGE_MARKERS = [
|
|
8
|
+
'et-rich-text-editor',
|
|
9
|
+
'RICH_TEXT_EDITOR_IMPORTS',
|
|
10
|
+
'RichTextEditorComponent',
|
|
11
|
+
'etRichTextEditor',
|
|
12
|
+
];
|
|
13
|
+
const OPT_IN_MARKER = 'provideRichTextEditorFloatingToolbar';
|
|
14
|
+
export const scanRichTextEditorFloatingToolbarInFile = (filePath, content) => {
|
|
15
|
+
const usages = [];
|
|
16
|
+
const marker = USAGE_MARKERS.find((m) => content.includes(m));
|
|
17
|
+
if (marker) {
|
|
18
|
+
const line = content.slice(0, content.indexOf(marker)).split('\n').length;
|
|
19
|
+
usages.push({
|
|
20
|
+
id: `rich-text-editor-floating-toolbar--${filePath.replace(/[^a-zA-Z0-9]+/g, '-')}`,
|
|
21
|
+
file: filePath,
|
|
22
|
+
line,
|
|
23
|
+
message: `Uses the rich text editor (\`${marker}\`). Selecting text no longer floats a toolbar over the selection unless it is provided.`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return { usages, hasFloatingToolbarProvider: content.includes(OPT_IN_MARKER) };
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=rich-text-editor-floating-toolbar.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "migrate-rich-text-editor-floating-toolbar",
|
|
4
|
+
"title": "Find rich text editor usage affected by the opt-in selection toolbar",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"projects": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": { "type": "string" },
|
|
10
|
+
"description": "Nx projects to scan. Defaults to every project in the workspace.",
|
|
11
|
+
"alias": "project"
|
|
12
|
+
},
|
|
13
|
+
"include": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" },
|
|
16
|
+
"description": "Path prefixes to scan, relative to the workspace root (e.g. 'apps/shop'). Unioned with `projects`.",
|
|
17
|
+
"alias": "includePath"
|
|
18
|
+
},
|
|
19
|
+
"skipFormat": {
|
|
20
|
+
"type": "boolean",
|
|
21
|
+
"description": "Skip formatting files after migration",
|
|
22
|
+
"default": false
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"required": []
|
|
26
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { formatFiles } from '@nx/devkit';
|
|
2
|
+
import { createMigrationScope } from '../migrate-query-error-labels/migration-scope.js';
|
|
3
|
+
import { scanRichTextEditorToolsInFile } from './rich-text-editor-tools.js';
|
|
4
|
+
export const RICH_TEXT_EDITOR_TOOLS_REPORT_PATH = 'rich-text-editor-tools-migration-tasks.md';
|
|
5
|
+
const renderReport = (tasks) => [
|
|
6
|
+
'# Rich text editor tools migration tasks',
|
|
7
|
+
'',
|
|
8
|
+
"The rich text editor's block-style menu, quotes, code blocks, links and markdown-as-you-type are opt-in.",
|
|
9
|
+
'Without a provider those four buttons render nothing and a typed `# ` / `> ` / ``` stays literal text, so',
|
|
10
|
+
'an editor that only needs marks and lists stops bundling any of it.',
|
|
11
|
+
'',
|
|
12
|
+
'To get the previous toolbar back, add once — app-wide, or on the component/route that renders the editor:',
|
|
13
|
+
'',
|
|
14
|
+
'```ts',
|
|
15
|
+
"import { provideRichTextEditorDefaultTools } from '@ethlete/components';",
|
|
16
|
+
'',
|
|
17
|
+
'provideRichTextEditorDefaultTools();',
|
|
18
|
+
'```',
|
|
19
|
+
'',
|
|
20
|
+
'For a smaller editor, register only what it offers instead:',
|
|
21
|
+
'`provideRichTextEditorHeadingTool()`, `provideRichTextEditorBlockquoteTool()`,',
|
|
22
|
+
'`provideRichTextEditorCodeBlockTool()`, `provideRichTextEditorLinkTool()`,',
|
|
23
|
+
'`provideRichTextEditorAutoformat()`.',
|
|
24
|
+
'',
|
|
25
|
+
'Calling `toggleBlockquote()`, `toggleHeading()`, `applyLink()` and friends without their provider throws',
|
|
26
|
+
'`ET2506` in dev mode and no-ops in production.',
|
|
27
|
+
'',
|
|
28
|
+
'If marks and lists are all the app needs, there is nothing to do — delete this file.',
|
|
29
|
+
'',
|
|
30
|
+
...tasks.map((task) => [`## \`${task.id}\``, '', `- ${task.file}:${task.line}`, `- ${task.message}`, ''].join('\n')),
|
|
31
|
+
].join('\n');
|
|
32
|
+
export default async function migrateRichTextEditorTools(tree, schema) {
|
|
33
|
+
console.log('\n🔎 Scanning for rich text editor usage affected by the opt-in tools...');
|
|
34
|
+
const scope = createMigrationScope(tree, schema);
|
|
35
|
+
console.log(` Scope: ${scope.describe()}`);
|
|
36
|
+
const tasks = [];
|
|
37
|
+
let hasToolProvider = false;
|
|
38
|
+
scope.visit(tree, (filePath) => {
|
|
39
|
+
if (!/\.(ts|html)$/.test(filePath) || filePath.endsWith('.d.ts'))
|
|
40
|
+
return;
|
|
41
|
+
const content = tree.read(filePath, 'utf-8');
|
|
42
|
+
if (!content)
|
|
43
|
+
return;
|
|
44
|
+
const result = scanRichTextEditorToolsInFile(filePath, content);
|
|
45
|
+
tasks.push(...result.usages);
|
|
46
|
+
hasToolProvider ||= result.hasToolProvider;
|
|
47
|
+
});
|
|
48
|
+
if (hasToolProvider) {
|
|
49
|
+
console.log(' ✓ Found a tool provider — the app already opts into the tools it wants.');
|
|
50
|
+
}
|
|
51
|
+
else if (tasks.length > 0) {
|
|
52
|
+
tree.write(RICH_TEXT_EDITOR_TOOLS_REPORT_PATH, renderReport(tasks));
|
|
53
|
+
}
|
|
54
|
+
if (!schema.skipFormat) {
|
|
55
|
+
await formatFiles(tree);
|
|
56
|
+
}
|
|
57
|
+
if (!hasToolProvider && tasks.length > 0) {
|
|
58
|
+
console.log(`\n⚠️ ${tasks.length} site(s) use the rich text editor without any tool provider — see ${RICH_TEXT_EDITOR_TOOLS_REPORT_PATH}.`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log('\n✅ Nothing to do.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rich text editor's heading, quote, code-block, link and autoformat behaviour is opt-in. An
|
|
3
|
+
* editor that provides none of it silently renders four fewer toolbar buttons and stops converting
|
|
4
|
+
* markdown as you type - no error, just less UI - so this migration finds the affected sites and
|
|
5
|
+
* reports them; it rewrites nothing.
|
|
6
|
+
*/
|
|
7
|
+
const USAGE_MARKERS = [
|
|
8
|
+
'et-rich-text-editor',
|
|
9
|
+
'RICH_TEXT_EDITOR_IMPORTS',
|
|
10
|
+
'RichTextEditorComponent',
|
|
11
|
+
'etRichTextEditor',
|
|
12
|
+
];
|
|
13
|
+
/** Any one of these means the app already knows about the split - `DefaultTools` or a single tool. */
|
|
14
|
+
const OPT_IN_MARKERS = [
|
|
15
|
+
'provideRichTextEditorDefaultTools',
|
|
16
|
+
'provideRichTextEditorHeadingTool',
|
|
17
|
+
'provideRichTextEditorBlockquoteTool',
|
|
18
|
+
'provideRichTextEditorCodeBlockTool',
|
|
19
|
+
'provideRichTextEditorLinkTool',
|
|
20
|
+
'provideRichTextEditorAutoformat',
|
|
21
|
+
];
|
|
22
|
+
export const scanRichTextEditorToolsInFile = (filePath, content) => {
|
|
23
|
+
const usages = [];
|
|
24
|
+
const marker = USAGE_MARKERS.find((m) => content.includes(m));
|
|
25
|
+
if (marker) {
|
|
26
|
+
const line = content.slice(0, content.indexOf(marker)).split('\n').length;
|
|
27
|
+
usages.push({
|
|
28
|
+
id: `rich-text-editor-tools--${filePath.replace(/[^a-zA-Z0-9]+/g, '-')}`,
|
|
29
|
+
file: filePath,
|
|
30
|
+
line,
|
|
31
|
+
message: `Uses the rich text editor (\`${marker}\`). Its heading, quote, code-block and link tools and its markdown autoformat only render/run when provided now.`,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return { usages, hasToolProvider: OPT_IN_MARKERS.some((m) => content.includes(m)) };
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=rich-text-editor-tools.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "migrate-rich-text-editor-tools",
|
|
4
|
+
"title": "Find rich text editor usage affected by the opt-in tools",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"projects": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": { "type": "string" },
|
|
10
|
+
"description": "Nx projects to scan. Defaults to every project in the workspace.",
|
|
11
|
+
"alias": "project"
|
|
12
|
+
},
|
|
13
|
+
"include": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" },
|
|
16
|
+
"description": "Path prefixes to scan, relative to the workspace root (e.g. 'apps/shop'). Unioned with `projects`.",
|
|
17
|
+
"alias": "includePath"
|
|
18
|
+
},
|
|
19
|
+
"skipFormat": {
|
|
20
|
+
"type": "boolean",
|
|
21
|
+
"description": "Skip formatting files after migration",
|
|
22
|
+
"default": false
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"required": []
|
|
26
|
+
}
|