ckeditor5-blazor 0.1.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/dist/ckeditor5-blazor-error.d.ts +7 -0
- package/dist/ckeditor5-blazor-error.d.ts.map +1 -0
- package/dist/elements/context/context.d.ts +26 -0
- package/dist/elements/context/context.d.ts.map +1 -0
- package/dist/elements/context/contexts-registry.d.ts +9 -0
- package/dist/elements/context/contexts-registry.d.ts.map +1 -0
- package/dist/elements/context/index.d.ts +4 -0
- package/dist/elements/context/index.d.ts.map +1 -0
- package/dist/elements/context/typings.d.ts +34 -0
- package/dist/elements/context/typings.d.ts.map +1 -0
- package/dist/elements/editable.d.ts +34 -0
- package/dist/elements/editable.d.ts.map +1 -0
- package/dist/elements/editor/custom-editor-plugins.d.ts +54 -0
- package/dist/elements/editor/custom-editor-plugins.d.ts.map +1 -0
- package/dist/elements/editor/editor.d.ts +31 -0
- package/dist/elements/editor/editor.d.ts.map +1 -0
- package/dist/elements/editor/editors-registry.d.ts +9 -0
- package/dist/elements/editor/editors-registry.d.ts.map +1 -0
- package/dist/elements/editor/index.d.ts +3 -0
- package/dist/elements/editor/index.d.ts.map +1 -0
- package/dist/elements/editor/plugins/dispatch-editor-roots-change-event.d.ts +23 -0
- package/dist/elements/editor/plugins/dispatch-editor-roots-change-event.d.ts.map +1 -0
- package/dist/elements/editor/plugins/index.d.ts +3 -0
- package/dist/elements/editor/plugins/index.d.ts.map +1 -0
- package/dist/elements/editor/plugins/sync-editor-with-input.d.ts +6 -0
- package/dist/elements/editor/plugins/sync-editor-with-input.d.ts.map +1 -0
- package/dist/elements/editor/typings.d.ts +99 -0
- package/dist/elements/editor/typings.d.ts.map +1 -0
- package/dist/elements/editor/utils/create-editor-in-context.d.ts +44 -0
- package/dist/elements/editor/utils/create-editor-in-context.d.ts.map +1 -0
- package/dist/elements/editor/utils/get-editor-roots-values.d.ts +9 -0
- package/dist/elements/editor/utils/get-editor-roots-values.d.ts.map +1 -0
- package/dist/elements/editor/utils/index.d.ts +14 -0
- package/dist/elements/editor/utils/index.d.ts.map +1 -0
- package/dist/elements/editor/utils/is-single-root-editor.d.ts +9 -0
- package/dist/elements/editor/utils/is-single-root-editor.d.ts.map +1 -0
- package/dist/elements/editor/utils/load-editor-constructor.d.ts +9 -0
- package/dist/elements/editor/utils/load-editor-constructor.d.ts.map +1 -0
- package/dist/elements/editor/utils/load-editor-plugins.d.ts +20 -0
- package/dist/elements/editor/utils/load-editor-plugins.d.ts.map +1 -0
- package/dist/elements/editor/utils/load-editor-translations.d.ts +14 -0
- package/dist/elements/editor/utils/load-editor-translations.d.ts.map +1 -0
- package/dist/elements/editor/utils/normalize-custom-translations.d.ts +11 -0
- package/dist/elements/editor/utils/normalize-custom-translations.d.ts.map +1 -0
- package/dist/elements/editor/utils/query-all-editor-ids.d.ts +5 -0
- package/dist/elements/editor/utils/query-all-editor-ids.d.ts.map +1 -0
- package/dist/elements/editor/utils/query-editor-editables.d.ts +25 -0
- package/dist/elements/editor/utils/query-editor-editables.d.ts.map +1 -0
- package/dist/elements/editor/utils/resolve-editor-config-elements-references.d.ts +9 -0
- package/dist/elements/editor/utils/resolve-editor-config-elements-references.d.ts.map +1 -0
- package/dist/elements/editor/utils/resolve-editor-config-translations.d.ts +25 -0
- package/dist/elements/editor/utils/resolve-editor-config-translations.d.ts.map +1 -0
- package/dist/elements/editor/utils/set-editor-editable-height.d.ts +9 -0
- package/dist/elements/editor/utils/set-editor-editable-height.d.ts.map +1 -0
- package/dist/elements/editor/utils/wrap-with-watchdog.d.ts +24 -0
- package/dist/elements/editor/utils/wrap-with-watchdog.d.ts.map +1 -0
- package/dist/elements/ensure-editor-elements-registered.d.ts +5 -0
- package/dist/elements/ensure-editor-elements-registered.d.ts.map +1 -0
- package/dist/elements/index.d.ts +6 -0
- package/dist/elements/index.d.ts.map +1 -0
- package/dist/elements/ui-part.d.ts +18 -0
- package/dist/elements/ui-part.d.ts.map +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +1400 -0
- package/dist/index.mjs.map +1 -0
- package/dist/interop/create-context-blazor-interop.d.ts +10 -0
- package/dist/interop/create-context-blazor-interop.d.ts.map +1 -0
- package/dist/interop/create-editable-blazor-interop.d.ts +21 -0
- package/dist/interop/create-editable-blazor-interop.d.ts.map +1 -0
- package/dist/interop/create-editor-blazor-interop.d.ts +19 -0
- package/dist/interop/create-editor-blazor-interop.d.ts.map +1 -0
- package/dist/interop/create-ui-part-blazor-interop.d.ts +10 -0
- package/dist/interop/create-ui-part-blazor-interop.d.ts.map +1 -0
- package/dist/interop/index.d.ts +5 -0
- package/dist/interop/index.d.ts.map +1 -0
- package/dist/interop/utils/create-editor-value-sync.d.ts +63 -0
- package/dist/interop/utils/create-editor-value-sync.d.ts.map +1 -0
- package/dist/interop/utils/index.d.ts +2 -0
- package/dist/interop/utils/index.d.ts.map +1 -0
- package/dist/shared/async-registry.d.ts +136 -0
- package/dist/shared/async-registry.d.ts.map +1 -0
- package/dist/shared/camel-case.d.ts +8 -0
- package/dist/shared/camel-case.d.ts.map +1 -0
- package/dist/shared/debounce.d.ts +2 -0
- package/dist/shared/debounce.d.ts.map +1 -0
- package/dist/shared/deep-camel-case-keys.d.ts +8 -0
- package/dist/shared/deep-camel-case-keys.d.ts.map +1 -0
- package/dist/shared/filter-object-values.d.ts +9 -0
- package/dist/shared/filter-object-values.d.ts.map +1 -0
- package/dist/shared/index.d.ts +16 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/is-empty-object.d.ts +2 -0
- package/dist/shared/is-empty-object.d.ts.map +1 -0
- package/dist/shared/is-plain-object.d.ts +8 -0
- package/dist/shared/is-plain-object.d.ts.map +1 -0
- package/dist/shared/map-object-values.d.ts +11 -0
- package/dist/shared/map-object-values.d.ts.map +1 -0
- package/dist/shared/once.d.ts +2 -0
- package/dist/shared/once.d.ts.map +1 -0
- package/dist/shared/shallow-equal.d.ts +9 -0
- package/dist/shared/shallow-equal.d.ts.map +1 -0
- package/dist/shared/timeout.d.ts +8 -0
- package/dist/shared/timeout.d.ts.map +1 -0
- package/dist/shared/uid.d.ts +7 -0
- package/dist/shared/uid.d.ts.map +1 -0
- package/dist/shared/wait-for-dom-ready.d.ts +5 -0
- package/dist/shared/wait-for-dom-ready.d.ts.map +1 -0
- package/dist/shared/wait-for-interactive-attribute.d.ts +18 -0
- package/dist/shared/wait-for-interactive-attribute.d.ts.map +1 -0
- package/dist/shared/wait-for.d.ts +20 -0
- package/dist/shared/wait-for.d.ts.map +1 -0
- package/dist/types/can-be-promise.type.d.ts +2 -0
- package/dist/types/can-be-promise.type.d.ts.map +1 -0
- package/dist/types/dot-net-interop.type.d.ts +7 -0
- package/dist/types/dot-net-interop.type.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/required-by.type.d.ts +2 -0
- package/dist/types/required-by.type.d.ts.map +1 -0
- package/package.json +49 -0
- package/src/ckeditor5-blazor-error.ts +9 -0
- package/src/elements/context/context.test.ts +323 -0
- package/src/elements/context/context.ts +128 -0
- package/src/elements/context/contexts-registry.test.ts +10 -0
- package/src/elements/context/contexts-registry.ts +10 -0
- package/src/elements/context/index.ts +3 -0
- package/src/elements/context/typings.ts +38 -0
- package/src/elements/editable.test.ts +383 -0
- package/src/elements/editable.ts +183 -0
- package/src/elements/editor/custom-editor-plugins.test.ts +103 -0
- package/src/elements/editor/custom-editor-plugins.ts +85 -0
- package/src/elements/editor/editor.test.ts +562 -0
- package/src/elements/editor/editor.ts +330 -0
- package/src/elements/editor/editors-registry.test.ts +10 -0
- package/src/elements/editor/editors-registry.ts +10 -0
- package/src/elements/editor/index.ts +2 -0
- package/src/elements/editor/plugins/dispatch-editor-roots-change-event.ts +76 -0
- package/src/elements/editor/plugins/index.ts +2 -0
- package/src/elements/editor/plugins/sync-editor-with-input.ts +79 -0
- package/src/elements/editor/typings.ts +114 -0
- package/src/elements/editor/utils/create-editor-in-context.ts +89 -0
- package/src/elements/editor/utils/get-editor-roots-values.test.ts +48 -0
- package/src/elements/editor/utils/get-editor-roots-values.ts +21 -0
- package/src/elements/editor/utils/index.ts +13 -0
- package/src/elements/editor/utils/is-single-root-editor.test.ts +40 -0
- package/src/elements/editor/utils/is-single-root-editor.ts +11 -0
- package/src/elements/editor/utils/load-editor-constructor.test.ts +62 -0
- package/src/elements/editor/utils/load-editor-constructor.ts +29 -0
- package/src/elements/editor/utils/load-editor-plugins.test.ts +100 -0
- package/src/elements/editor/utils/load-editor-plugins.ts +72 -0
- package/src/elements/editor/utils/load-editor-translations.ts +232 -0
- package/src/elements/editor/utils/normalize-custom-translations.test.ts +152 -0
- package/src/elements/editor/utils/normalize-custom-translations.ts +17 -0
- package/src/elements/editor/utils/query-all-editor-ids.ts +9 -0
- package/src/elements/editor/utils/query-editor-editables.ts +101 -0
- package/src/elements/editor/utils/resolve-editor-config-elements-references.test.ts +93 -0
- package/src/elements/editor/utils/resolve-editor-config-elements-references.ts +36 -0
- package/src/elements/editor/utils/resolve-editor-config-translations.test.ts +131 -0
- package/src/elements/editor/utils/resolve-editor-config-translations.ts +77 -0
- package/src/elements/editor/utils/set-editor-editable-height.test.ts +131 -0
- package/src/elements/editor/utils/set-editor-editable-height.ts +15 -0
- package/src/elements/editor/utils/wrap-with-watchdog.test.ts +45 -0
- package/src/elements/editor/utils/wrap-with-watchdog.ts +51 -0
- package/src/elements/ensure-editor-elements-registered.ts +24 -0
- package/src/elements/index.ts +14 -0
- package/src/elements/ui-part.test.ts +156 -0
- package/src/elements/ui-part.ts +84 -0
- package/src/index.ts +15 -0
- package/src/interop/create-context-blazor-interop.test.ts +30 -0
- package/src/interop/create-context-blazor-interop.ts +15 -0
- package/src/interop/create-editable-blazor-interop.test.ts +213 -0
- package/src/interop/create-editable-blazor-interop.ts +98 -0
- package/src/interop/create-editor-blazor-interop.test.ts +183 -0
- package/src/interop/create-editor-blazor-interop.ts +112 -0
- package/src/interop/create-ui-part-blazor-interop.test.ts +30 -0
- package/src/interop/create-ui-part-blazor-interop.ts +15 -0
- package/src/interop/index.ts +4 -0
- package/src/interop/utils/create-editor-value-sync.test.ts +302 -0
- package/src/interop/utils/create-editor-value-sync.ts +160 -0
- package/src/interop/utils/index.ts +1 -0
- package/src/shared/async-registry.test.ts +737 -0
- package/src/shared/async-registry.ts +353 -0
- package/src/shared/camel-case.test.ts +35 -0
- package/src/shared/camel-case.ts +11 -0
- package/src/shared/debounce.test.ts +72 -0
- package/src/shared/debounce.ts +16 -0
- package/src/shared/deep-camel-case-keys.test.ts +34 -0
- package/src/shared/deep-camel-case-keys.ts +26 -0
- package/src/shared/filter-object-values.test.ts +25 -0
- package/src/shared/filter-object-values.ts +17 -0
- package/src/shared/index.ts +15 -0
- package/src/shared/is-empty-object.test.ts +78 -0
- package/src/shared/is-empty-object.ts +3 -0
- package/src/shared/is-plain-object.test.ts +38 -0
- package/src/shared/is-plain-object.ts +15 -0
- package/src/shared/map-object-values.test.ts +29 -0
- package/src/shared/map-object-values.ts +19 -0
- package/src/shared/once.test.ts +116 -0
- package/src/shared/once.ts +12 -0
- package/src/shared/shallow-equal.test.ts +51 -0
- package/src/shared/shallow-equal.ts +30 -0
- package/src/shared/timeout.test.ts +65 -0
- package/src/shared/timeout.ts +13 -0
- package/src/shared/uid.test.ts +25 -0
- package/src/shared/uid.ts +8 -0
- package/src/shared/wait-for-dom-ready.test.ts +87 -0
- package/src/shared/wait-for-dom-ready.ts +21 -0
- package/src/shared/wait-for-interactive-attribute.test.ts +93 -0
- package/src/shared/wait-for-interactive-attribute.ts +50 -0
- package/src/shared/wait-for.test.ts +24 -0
- package/src/shared/wait-for.ts +56 -0
- package/src/types/can-be-promise.type.ts +1 -0
- package/src/types/dot-net-interop.type.ts +6 -0
- package/src/types/dotnet-global.d.ts +14 -0
- package/src/types/index.ts +3 -0
- package/src/types/required-by.type.ts +1 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads all required translations for the editor based on the language configuration.
|
|
3
|
+
*
|
|
4
|
+
* @param language - The language configuration object containing UI and content language codes.
|
|
5
|
+
* @param language.ui - The UI language code.
|
|
6
|
+
* @param language.content - The content language code.
|
|
7
|
+
* @param hasPremium - Whether premium features are enabled and premium translations should be loaded.
|
|
8
|
+
* @returns A promise that resolves to an array of loaded translation objects.
|
|
9
|
+
*/
|
|
10
|
+
export async function loadAllEditorTranslations(
|
|
11
|
+
language: { ui: string; content: string; },
|
|
12
|
+
hasPremium: boolean,
|
|
13
|
+
) {
|
|
14
|
+
const translations = [language.ui, language.content];
|
|
15
|
+
const loadedTranslations = await Promise.all(
|
|
16
|
+
[
|
|
17
|
+
loadEditorPkgTranslations('ckeditor5', translations),
|
|
18
|
+
|
|
19
|
+
/* v8 ignore next -- @preserve */
|
|
20
|
+
hasPremium && loadEditorPkgTranslations('ckeditor5-premium-features', translations),
|
|
21
|
+
].filter(pkg => !!pkg),
|
|
22
|
+
)
|
|
23
|
+
.then(translations => translations.flat());
|
|
24
|
+
|
|
25
|
+
return loadedTranslations;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Loads the editor translations for the given languages.
|
|
30
|
+
*
|
|
31
|
+
* Make sure this function is properly compiled and bundled in self hosted environments!
|
|
32
|
+
*
|
|
33
|
+
* @param pkg - The package to load translations from ('ckeditor5' or 'ckeditor5-premium-features').
|
|
34
|
+
* @param translations - The list of language codes to load translations for.
|
|
35
|
+
* @returns A promise that resolves to an array of loaded translation packs.
|
|
36
|
+
*/
|
|
37
|
+
async function loadEditorPkgTranslations(
|
|
38
|
+
pkg: EditorPkgName,
|
|
39
|
+
translations: string[],
|
|
40
|
+
) {
|
|
41
|
+
return await Promise.all(
|
|
42
|
+
translations
|
|
43
|
+
.filter(lang => lang !== 'en') // 'en' is the default language, no need to load it.
|
|
44
|
+
.map(async (lang) => {
|
|
45
|
+
const pack = await loadEditorTranslation(pkg, lang);
|
|
46
|
+
|
|
47
|
+
/* v8 ignore next -- @preserve */
|
|
48
|
+
return pack?.default ?? pack;
|
|
49
|
+
})
|
|
50
|
+
.filter(Boolean),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Type representing the package name for CKEditor 5.
|
|
56
|
+
*/
|
|
57
|
+
type EditorPkgName = 'ckeditor5' | 'ckeditor5-premium-features';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Load translation for CKEditor 5
|
|
61
|
+
* @param pkg - Package type: 'ckeditor5' or 'premium'
|
|
62
|
+
* @param lang - Language code (e.g., 'pl', 'en', 'de')
|
|
63
|
+
* @returns Translation object or null if failed
|
|
64
|
+
*/
|
|
65
|
+
async function loadEditorTranslation(pkg: EditorPkgName, lang: string): Promise<any> {
|
|
66
|
+
try {
|
|
67
|
+
/* v8 ignore next if -- @preserve */
|
|
68
|
+
if (pkg === 'ckeditor5') {
|
|
69
|
+
switch (lang) {
|
|
70
|
+
case 'af': return await import('ckeditor5/translations/af.js');
|
|
71
|
+
case 'ar': return await import('ckeditor5/translations/ar.js');
|
|
72
|
+
case 'ast': return await import('ckeditor5/translations/ast.js');
|
|
73
|
+
case 'az': return await import('ckeditor5/translations/az.js');
|
|
74
|
+
case 'bg': return await import('ckeditor5/translations/bg.js');
|
|
75
|
+
case 'bn': return await import('ckeditor5/translations/bn.js');
|
|
76
|
+
case 'bs': return await import('ckeditor5/translations/bs.js');
|
|
77
|
+
case 'ca': return await import('ckeditor5/translations/ca.js');
|
|
78
|
+
case 'cs': return await import('ckeditor5/translations/cs.js');
|
|
79
|
+
case 'da': return await import('ckeditor5/translations/da.js');
|
|
80
|
+
case 'de': return await import('ckeditor5/translations/de.js');
|
|
81
|
+
case 'de-ch': return await import('ckeditor5/translations/de-ch.js');
|
|
82
|
+
case 'el': return await import('ckeditor5/translations/el.js');
|
|
83
|
+
case 'en': return await import('ckeditor5/translations/en.js');
|
|
84
|
+
case 'en-au': return await import('ckeditor5/translations/en-au.js');
|
|
85
|
+
case 'en-gb': return await import('ckeditor5/translations/en-gb.js');
|
|
86
|
+
case 'eo': return await import('ckeditor5/translations/eo.js');
|
|
87
|
+
case 'es': return await import('ckeditor5/translations/es.js');
|
|
88
|
+
case 'es-co': return await import('ckeditor5/translations/es-co.js');
|
|
89
|
+
case 'et': return await import('ckeditor5/translations/et.js');
|
|
90
|
+
case 'eu': return await import('ckeditor5/translations/eu.js');
|
|
91
|
+
case 'fa': return await import('ckeditor5/translations/fa.js');
|
|
92
|
+
case 'fi': return await import('ckeditor5/translations/fi.js');
|
|
93
|
+
case 'fr': return await import('ckeditor5/translations/fr.js');
|
|
94
|
+
case 'gl': return await import('ckeditor5/translations/gl.js');
|
|
95
|
+
case 'gu': return await import('ckeditor5/translations/gu.js');
|
|
96
|
+
case 'he': return await import('ckeditor5/translations/he.js');
|
|
97
|
+
case 'hi': return await import('ckeditor5/translations/hi.js');
|
|
98
|
+
case 'hr': return await import('ckeditor5/translations/hr.js');
|
|
99
|
+
case 'hu': return await import('ckeditor5/translations/hu.js');
|
|
100
|
+
case 'hy': return await import('ckeditor5/translations/hy.js');
|
|
101
|
+
case 'id': return await import('ckeditor5/translations/id.js');
|
|
102
|
+
case 'it': return await import('ckeditor5/translations/it.js');
|
|
103
|
+
case 'ja': return await import('ckeditor5/translations/ja.js');
|
|
104
|
+
case 'jv': return await import('ckeditor5/translations/jv.js');
|
|
105
|
+
case 'kk': return await import('ckeditor5/translations/kk.js');
|
|
106
|
+
case 'km': return await import('ckeditor5/translations/km.js');
|
|
107
|
+
case 'kn': return await import('ckeditor5/translations/kn.js');
|
|
108
|
+
case 'ko': return await import('ckeditor5/translations/ko.js');
|
|
109
|
+
case 'ku': return await import('ckeditor5/translations/ku.js');
|
|
110
|
+
case 'lt': return await import('ckeditor5/translations/lt.js');
|
|
111
|
+
case 'lv': return await import('ckeditor5/translations/lv.js');
|
|
112
|
+
case 'ms': return await import('ckeditor5/translations/ms.js');
|
|
113
|
+
case 'nb': return await import('ckeditor5/translations/nb.js');
|
|
114
|
+
case 'ne': return await import('ckeditor5/translations/ne.js');
|
|
115
|
+
case 'nl': return await import('ckeditor5/translations/nl.js');
|
|
116
|
+
case 'no': return await import('ckeditor5/translations/no.js');
|
|
117
|
+
case 'oc': return await import('ckeditor5/translations/oc.js');
|
|
118
|
+
case 'pl': return await import('ckeditor5/translations/pl.js');
|
|
119
|
+
case 'pt': return await import('ckeditor5/translations/pt.js');
|
|
120
|
+
case 'pt-br': return await import('ckeditor5/translations/pt-br.js');
|
|
121
|
+
case 'ro': return await import('ckeditor5/translations/ro.js');
|
|
122
|
+
case 'ru': return await import('ckeditor5/translations/ru.js');
|
|
123
|
+
case 'si': return await import('ckeditor5/translations/si.js');
|
|
124
|
+
case 'sk': return await import('ckeditor5/translations/sk.js');
|
|
125
|
+
case 'sl': return await import('ckeditor5/translations/sl.js');
|
|
126
|
+
case 'sq': return await import('ckeditor5/translations/sq.js');
|
|
127
|
+
case 'sr': return await import('ckeditor5/translations/sr.js');
|
|
128
|
+
case 'sr-latn': return await import('ckeditor5/translations/sr-latn.js');
|
|
129
|
+
case 'sv': return await import('ckeditor5/translations/sv.js');
|
|
130
|
+
case 'th': return await import('ckeditor5/translations/th.js');
|
|
131
|
+
case 'tk': return await import('ckeditor5/translations/tk.js');
|
|
132
|
+
case 'tr': return await import('ckeditor5/translations/tr.js');
|
|
133
|
+
case 'tt': return await import('ckeditor5/translations/tt.js');
|
|
134
|
+
case 'ug': return await import('ckeditor5/translations/ug.js');
|
|
135
|
+
case 'uk': return await import('ckeditor5/translations/uk.js');
|
|
136
|
+
case 'ur': return await import('ckeditor5/translations/ur.js');
|
|
137
|
+
case 'uz': return await import('ckeditor5/translations/uz.js');
|
|
138
|
+
case 'vi': return await import('ckeditor5/translations/vi.js');
|
|
139
|
+
case 'zh': return await import('ckeditor5/translations/zh.js');
|
|
140
|
+
case 'zh-cn': return await import('ckeditor5/translations/zh-cn.js');
|
|
141
|
+
default:
|
|
142
|
+
console.warn(`Language ${lang} not found in ckeditor5 translations`);
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// Premium features translations
|
|
148
|
+
switch (lang) {
|
|
149
|
+
case 'af': return await import('ckeditor5-premium-features/translations/af.js');
|
|
150
|
+
case 'ar': return await import('ckeditor5-premium-features/translations/ar.js');
|
|
151
|
+
case 'ast': return await import('ckeditor5-premium-features/translations/ast.js');
|
|
152
|
+
case 'az': return await import('ckeditor5-premium-features/translations/az.js');
|
|
153
|
+
case 'bg': return await import('ckeditor5-premium-features/translations/bg.js');
|
|
154
|
+
case 'bn': return await import('ckeditor5-premium-features/translations/bn.js');
|
|
155
|
+
case 'bs': return await import('ckeditor5-premium-features/translations/bs.js');
|
|
156
|
+
case 'ca': return await import('ckeditor5-premium-features/translations/ca.js');
|
|
157
|
+
case 'cs': return await import('ckeditor5-premium-features/translations/cs.js');
|
|
158
|
+
case 'da': return await import('ckeditor5-premium-features/translations/da.js');
|
|
159
|
+
case 'de': return await import('ckeditor5-premium-features/translations/de.js');
|
|
160
|
+
case 'de-ch': return await import('ckeditor5-premium-features/translations/de-ch.js');
|
|
161
|
+
case 'el': return await import('ckeditor5-premium-features/translations/el.js');
|
|
162
|
+
case 'en': return await import('ckeditor5-premium-features/translations/en.js');
|
|
163
|
+
case 'en-au': return await import('ckeditor5-premium-features/translations/en-au.js');
|
|
164
|
+
case 'en-gb': return await import('ckeditor5-premium-features/translations/en-gb.js');
|
|
165
|
+
case 'eo': return await import('ckeditor5-premium-features/translations/eo.js');
|
|
166
|
+
case 'es': return await import('ckeditor5-premium-features/translations/es.js');
|
|
167
|
+
case 'es-co': return await import('ckeditor5-premium-features/translations/es-co.js');
|
|
168
|
+
case 'et': return await import('ckeditor5-premium-features/translations/et.js');
|
|
169
|
+
case 'eu': return await import('ckeditor5-premium-features/translations/eu.js');
|
|
170
|
+
case 'fa': return await import('ckeditor5-premium-features/translations/fa.js');
|
|
171
|
+
case 'fi': return await import('ckeditor5-premium-features/translations/fi.js');
|
|
172
|
+
case 'fr': return await import('ckeditor5-premium-features/translations/fr.js');
|
|
173
|
+
case 'gl': return await import('ckeditor5-premium-features/translations/gl.js');
|
|
174
|
+
case 'gu': return await import('ckeditor5-premium-features/translations/gu.js');
|
|
175
|
+
case 'he': return await import('ckeditor5-premium-features/translations/he.js');
|
|
176
|
+
case 'hi': return await import('ckeditor5-premium-features/translations/hi.js');
|
|
177
|
+
case 'hr': return await import('ckeditor5-premium-features/translations/hr.js');
|
|
178
|
+
case 'hu': return await import('ckeditor5-premium-features/translations/hu.js');
|
|
179
|
+
case 'hy': return await import('ckeditor5-premium-features/translations/hy.js');
|
|
180
|
+
case 'id': return await import('ckeditor5-premium-features/translations/id.js');
|
|
181
|
+
case 'it': return await import('ckeditor5-premium-features/translations/it.js');
|
|
182
|
+
case 'ja': return await import('ckeditor5-premium-features/translations/ja.js');
|
|
183
|
+
case 'jv': return await import('ckeditor5-premium-features/translations/jv.js');
|
|
184
|
+
case 'kk': return await import('ckeditor5-premium-features/translations/kk.js');
|
|
185
|
+
case 'km': return await import('ckeditor5-premium-features/translations/km.js');
|
|
186
|
+
case 'kn': return await import('ckeditor5-premium-features/translations/kn.js');
|
|
187
|
+
case 'ko': return await import('ckeditor5-premium-features/translations/ko.js');
|
|
188
|
+
case 'ku': return await import('ckeditor5-premium-features/translations/ku.js');
|
|
189
|
+
case 'lt': return await import('ckeditor5-premium-features/translations/lt.js');
|
|
190
|
+
case 'lv': return await import('ckeditor5-premium-features/translations/lv.js');
|
|
191
|
+
case 'ms': return await import('ckeditor5-premium-features/translations/ms.js');
|
|
192
|
+
case 'nb': return await import('ckeditor5-premium-features/translations/nb.js');
|
|
193
|
+
case 'ne': return await import('ckeditor5-premium-features/translations/ne.js');
|
|
194
|
+
case 'nl': return await import('ckeditor5-premium-features/translations/nl.js');
|
|
195
|
+
case 'no': return await import('ckeditor5-premium-features/translations/no.js');
|
|
196
|
+
case 'oc': return await import('ckeditor5-premium-features/translations/oc.js');
|
|
197
|
+
case 'pl': return await import('ckeditor5-premium-features/translations/pl.js');
|
|
198
|
+
case 'pt': return await import('ckeditor5-premium-features/translations/pt.js');
|
|
199
|
+
case 'pt-br': return await import('ckeditor5-premium-features/translations/pt-br.js');
|
|
200
|
+
case 'ro': return await import('ckeditor5-premium-features/translations/ro.js');
|
|
201
|
+
case 'ru': return await import('ckeditor5-premium-features/translations/ru.js');
|
|
202
|
+
case 'si': return await import('ckeditor5-premium-features/translations/si.js');
|
|
203
|
+
case 'sk': return await import('ckeditor5-premium-features/translations/sk.js');
|
|
204
|
+
case 'sl': return await import('ckeditor5-premium-features/translations/sl.js');
|
|
205
|
+
case 'sq': return await import('ckeditor5-premium-features/translations/sq.js');
|
|
206
|
+
case 'sr': return await import('ckeditor5-premium-features/translations/sr.js');
|
|
207
|
+
case 'sr-latn': return await import('ckeditor5-premium-features/translations/sr-latn.js');
|
|
208
|
+
case 'sv': return await import('ckeditor5-premium-features/translations/sv.js');
|
|
209
|
+
case 'th': return await import('ckeditor5-premium-features/translations/th.js');
|
|
210
|
+
case 'tk': return await import('ckeditor5-premium-features/translations/tk.js');
|
|
211
|
+
case 'tr': return await import('ckeditor5-premium-features/translations/tr.js');
|
|
212
|
+
case 'tt': return await import('ckeditor5-premium-features/translations/tt.js');
|
|
213
|
+
case 'ug': return await import('ckeditor5-premium-features/translations/ug.js');
|
|
214
|
+
case 'uk': return await import('ckeditor5-premium-features/translations/uk.js');
|
|
215
|
+
case 'ur': return await import('ckeditor5-premium-features/translations/ur.js');
|
|
216
|
+
case 'uz': return await import('ckeditor5-premium-features/translations/uz.js');
|
|
217
|
+
case 'vi': return await import('ckeditor5-premium-features/translations/vi.js');
|
|
218
|
+
case 'zh': return await import('ckeditor5-premium-features/translations/zh.js');
|
|
219
|
+
case 'zh-cn': return await import('ckeditor5-premium-features/translations/zh-cn.js');
|
|
220
|
+
default:
|
|
221
|
+
console.warn(`Language ${lang} not found in premium translations`);
|
|
222
|
+
return await import('ckeditor5-premium-features/translations/en.js'); // fallback to English
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/* v8 ignore start -- @preserve */
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error(`Failed to load translation for ${pkg}/${lang}:`, error);
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
/* v8 ignore stop -- @preserve */
|
|
232
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { EditorCustomTranslationsDictionary } from '../typings';
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { normalizeCustomTranslations } from './normalize-custom-translations';
|
|
6
|
+
|
|
7
|
+
describe('normalizeCustomTranslations', () => {
|
|
8
|
+
it('should normalize empty translations object', () => {
|
|
9
|
+
const input: EditorCustomTranslationsDictionary = {};
|
|
10
|
+
const result = normalizeCustomTranslations(input);
|
|
11
|
+
|
|
12
|
+
expect(result).toEqual({});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should normalize single language translation', () => {
|
|
16
|
+
const input: EditorCustomTranslationsDictionary = {
|
|
17
|
+
en: {
|
|
18
|
+
Bold: 'Bold Text',
|
|
19
|
+
Italic: 'Italic Text',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const result = normalizeCustomTranslations(input);
|
|
24
|
+
|
|
25
|
+
expect(result).toEqual({
|
|
26
|
+
en: {
|
|
27
|
+
dictionary: {
|
|
28
|
+
Bold: 'Bold Text',
|
|
29
|
+
Italic: 'Italic Text',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should normalize multiple language translations', () => {
|
|
36
|
+
const input: EditorCustomTranslationsDictionary = {
|
|
37
|
+
en: {
|
|
38
|
+
Bold: 'Bold Text',
|
|
39
|
+
Italic: 'Italic Text',
|
|
40
|
+
},
|
|
41
|
+
pl: {
|
|
42
|
+
Bold: 'Pogrubienie',
|
|
43
|
+
Italic: 'Kursywa',
|
|
44
|
+
},
|
|
45
|
+
de: {
|
|
46
|
+
Bold: 'Fett',
|
|
47
|
+
Italic: 'Kursiv',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const result = normalizeCustomTranslations(input);
|
|
52
|
+
|
|
53
|
+
expect(result).toEqual({
|
|
54
|
+
en: {
|
|
55
|
+
dictionary: {
|
|
56
|
+
Bold: 'Bold Text',
|
|
57
|
+
Italic: 'Italic Text',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
pl: {
|
|
61
|
+
dictionary: {
|
|
62
|
+
Bold: 'Pogrubienie',
|
|
63
|
+
Italic: 'Kursywa',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
de: {
|
|
67
|
+
dictionary: {
|
|
68
|
+
Bold: 'Fett',
|
|
69
|
+
Italic: 'Kursiv',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should handle empty dictionary for a language', () => {
|
|
76
|
+
const input: EditorCustomTranslationsDictionary = {
|
|
77
|
+
en: {},
|
|
78
|
+
pl: {
|
|
79
|
+
Bold: 'Pogrubienie',
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const result = normalizeCustomTranslations(input);
|
|
84
|
+
|
|
85
|
+
expect(result).toEqual({
|
|
86
|
+
en: {
|
|
87
|
+
dictionary: {},
|
|
88
|
+
},
|
|
89
|
+
pl: {
|
|
90
|
+
dictionary: {
|
|
91
|
+
Bold: 'Pogrubienie',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should preserve special characters and unicode in translations', () => {
|
|
98
|
+
const input: EditorCustomTranslationsDictionary = {
|
|
99
|
+
zh: {
|
|
100
|
+
粗体: '加粗文本',
|
|
101
|
+
斜体: '斜体文本',
|
|
102
|
+
},
|
|
103
|
+
ar: {
|
|
104
|
+
Bold: 'عريض',
|
|
105
|
+
Italic: 'مائل',
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const result = normalizeCustomTranslations(input);
|
|
110
|
+
|
|
111
|
+
expect(result).toEqual({
|
|
112
|
+
zh: {
|
|
113
|
+
dictionary: {
|
|
114
|
+
粗体: '加粗文本',
|
|
115
|
+
斜体: '斜体文本',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
ar: {
|
|
119
|
+
dictionary: {
|
|
120
|
+
Bold: 'عريض',
|
|
121
|
+
Italic: 'مائل',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should handle language codes with regions', () => {
|
|
128
|
+
const input: EditorCustomTranslationsDictionary = {
|
|
129
|
+
'en-US': {
|
|
130
|
+
Color: 'Color',
|
|
131
|
+
},
|
|
132
|
+
'en-GB': {
|
|
133
|
+
Color: 'Colour',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const result = normalizeCustomTranslations(input);
|
|
138
|
+
|
|
139
|
+
expect(result).toEqual({
|
|
140
|
+
'en-US': {
|
|
141
|
+
dictionary: {
|
|
142
|
+
Color: 'Color',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
'en-GB': {
|
|
146
|
+
dictionary: {
|
|
147
|
+
Color: 'Colour',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EditorCustomTranslationsDictionary } from '../typings';
|
|
2
|
+
import type { Translations } from 'ckeditor5';
|
|
3
|
+
|
|
4
|
+
import { mapObjectValues } from '../../../shared';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This function takes a custom translations object and maps it to the format expected by CKEditor5.
|
|
8
|
+
* Each translation dictionary is wrapped in an object with a `dictionary` key.
|
|
9
|
+
*
|
|
10
|
+
* @param translations - The custom translations to normalize.
|
|
11
|
+
* @returns A normalized translations object suitable for CKEditor5.
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeCustomTranslations(translations: EditorCustomTranslationsDictionary): Translations {
|
|
14
|
+
return mapObjectValues(translations, dictionary => ({
|
|
15
|
+
dictionary,
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queries all CKEditor 5 editor IDs present in the document.
|
|
3
|
+
*/
|
|
4
|
+
export function queryAllEditorIds(): string[] {
|
|
5
|
+
return Array
|
|
6
|
+
.from(document.querySelectorAll<HTMLElement>('cke5-editor'))
|
|
7
|
+
.map(element => element.getAttribute('data-cke-editor-id'))
|
|
8
|
+
.filter((id): id is string => id !== null);
|
|
9
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { EditorId } from '../typings';
|
|
2
|
+
|
|
3
|
+
import { filterObjectValues, mapObjectValues } from '../../../shared';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Gets the initial root elements for the editor based on its type.
|
|
7
|
+
*
|
|
8
|
+
* @param editorId The editor's ID.
|
|
9
|
+
* @returns The root element(s) for the editor.
|
|
10
|
+
*/
|
|
11
|
+
export function queryEditablesElements(editorId: EditorId) {
|
|
12
|
+
const editables = queryAllEditorEditables(editorId);
|
|
13
|
+
|
|
14
|
+
return mapObjectValues(editables, ({ element }) => element);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Gets the initial data for the roots of the editor. If the editor is a single editing-like editor,
|
|
19
|
+
* it retrieves the initial value from the element's attribute. Otherwise, it returns an object mapping
|
|
20
|
+
* editable names to their initial values.
|
|
21
|
+
*
|
|
22
|
+
* @param editorId The editor's ID.
|
|
23
|
+
* @returns The initial values for the editor's roots.
|
|
24
|
+
*/
|
|
25
|
+
export function queryEditablesSnapshotContent(editorId: EditorId) {
|
|
26
|
+
const editables = queryAllEditorEditables(editorId);
|
|
27
|
+
const values = mapObjectValues(editables, ({ content }) => content);
|
|
28
|
+
|
|
29
|
+
return filterObjectValues(values, value => typeof value === 'string') as Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Queries all editable elements within a specific editor instance. It picks
|
|
34
|
+
* initial values from actually rendered elements or from the editor container's.
|
|
35
|
+
*
|
|
36
|
+
* It may differ from the `initialData` used during editor creation, as it might
|
|
37
|
+
* not set all roots or set different values.
|
|
38
|
+
*
|
|
39
|
+
* @param editorId The ID of the editor to query.
|
|
40
|
+
* @returns An object mapping editable names to their corresponding elements and initial values.
|
|
41
|
+
*/
|
|
42
|
+
function queryAllEditorEditables(editorId: EditorId) {
|
|
43
|
+
const acc = (
|
|
44
|
+
Array
|
|
45
|
+
.from(document.querySelectorAll<HTMLElement>(`cke5-editable[data-cke-editor-id="${editorId}"]`))
|
|
46
|
+
.reduce<Record<string, EditableItem>>((acc, element) => {
|
|
47
|
+
const rootName = element.getAttribute('data-cke-root-name')!;
|
|
48
|
+
const content = element.getAttribute('data-cke-content');
|
|
49
|
+
|
|
50
|
+
acc[rootName] = {
|
|
51
|
+
element: element.querySelector<HTMLElement>('[data-cke-editable-content]')!,
|
|
52
|
+
content,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return acc;
|
|
56
|
+
}, Object.create({}))
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const editor = document.querySelector<HTMLElement>(`cke5-editor[data-cke-editor-id="${editorId}"]`);
|
|
60
|
+
|
|
61
|
+
/* v8 ignore next -- @preserve */
|
|
62
|
+
if (!editor) {
|
|
63
|
+
return acc;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const currentMain = acc['main'];
|
|
67
|
+
const initialRootEditableValue = JSON.parse(editor.getAttribute('data-cke-content')!);
|
|
68
|
+
const contentElement = document.querySelector<HTMLElement>(`#${editorId}_editor `);
|
|
69
|
+
|
|
70
|
+
// If found `main` editable, but it has no content, try to fill it from the editor container.
|
|
71
|
+
if (currentMain && initialRootEditableValue?.['main']) {
|
|
72
|
+
return {
|
|
73
|
+
...acc,
|
|
74
|
+
main: {
|
|
75
|
+
...currentMain,
|
|
76
|
+
content: currentMain.content || initialRootEditableValue['main'],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// If no `main` editable found, try to create it from the editor container.
|
|
82
|
+
if (contentElement) {
|
|
83
|
+
return {
|
|
84
|
+
...acc,
|
|
85
|
+
main: {
|
|
86
|
+
element: contentElement,
|
|
87
|
+
content: initialRootEditableValue?.['main'] || null,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return acc;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Type representing an editable item within an editor.
|
|
97
|
+
*/
|
|
98
|
+
export type EditableItem = {
|
|
99
|
+
element: HTMLElement;
|
|
100
|
+
content: string | null;
|
|
101
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { resolveEditorConfigElementReferences } from './resolve-editor-config-elements-references';
|
|
4
|
+
|
|
5
|
+
describe('resolveEditorConfigElementReferences', () => {
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
document.body.innerHTML = '';
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('resolves a single element reference', () => {
|
|
11
|
+
const div = document.createElement('div');
|
|
12
|
+
div.id = 'test-div';
|
|
13
|
+
document.body.appendChild(div);
|
|
14
|
+
|
|
15
|
+
const config = {
|
|
16
|
+
foo: { $element: '#test-div' },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const result = resolveEditorConfigElementReferences(config);
|
|
20
|
+
expect(result.foo).toBe(div);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('returns null if element not found', () => {
|
|
24
|
+
const config = {
|
|
25
|
+
foo: { $element: '#not-exist' },
|
|
26
|
+
};
|
|
27
|
+
const result = resolveEditorConfigElementReferences(config);
|
|
28
|
+
|
|
29
|
+
expect(result.foo).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('recursively resolves nested element references', () => {
|
|
33
|
+
const span = document.createElement('span');
|
|
34
|
+
span.className = 'my-span';
|
|
35
|
+
document.body.appendChild(span);
|
|
36
|
+
|
|
37
|
+
const config = {
|
|
38
|
+
nested: {
|
|
39
|
+
bar: { $element: '.my-span' },
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const result = resolveEditorConfigElementReferences(config);
|
|
44
|
+
expect(result.nested.bar).toBe(span);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('resolves element references in arrays', () => {
|
|
48
|
+
const el1 = document.createElement('div');
|
|
49
|
+
el1.id = 'el1';
|
|
50
|
+
document.body.appendChild(el1);
|
|
51
|
+
|
|
52
|
+
const el2 = document.createElement('div');
|
|
53
|
+
el2.id = 'el2';
|
|
54
|
+
document.body.appendChild(el2);
|
|
55
|
+
|
|
56
|
+
const config = [
|
|
57
|
+
{ $element: '#el1' },
|
|
58
|
+
{ $element: '#el2' },
|
|
59
|
+
{ notElement: 123 },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const result = resolveEditorConfigElementReferences(config);
|
|
63
|
+
|
|
64
|
+
expect(result[0]).toBe(el1);
|
|
65
|
+
expect(result[1]).toBe(el2);
|
|
66
|
+
expect(result[2]).toEqual({ notElement: 123 });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('returns primitives as is', () => {
|
|
70
|
+
expect(resolveEditorConfigElementReferences(42)).toBe(42);
|
|
71
|
+
expect(resolveEditorConfigElementReferences('foo')).toBe('foo');
|
|
72
|
+
expect(resolveEditorConfigElementReferences(null)).toBe(null);
|
|
73
|
+
expect(resolveEditorConfigElementReferences(undefined)).toBe(undefined);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('warns for invalid selector type', () => {
|
|
77
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
78
|
+
const config = { foo: { $element: '.foo' } };
|
|
79
|
+
|
|
80
|
+
resolveEditorConfigElementReferences(config);
|
|
81
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Element not found for selector: .foo'));
|
|
82
|
+
warnSpy.mockRestore();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('warns if element not found', () => {
|
|
86
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
87
|
+
const config = { foo: { $element: '#not-found' } };
|
|
88
|
+
|
|
89
|
+
resolveEditorConfigElementReferences(config);
|
|
90
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Element not found'));
|
|
91
|
+
warnSpy.mockRestore();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves element references in configuration object.
|
|
3
|
+
* Looks for objects with { $element: "selector" } format and replaces them with actual DOM elements.
|
|
4
|
+
*
|
|
5
|
+
* @param obj - Configuration object to process
|
|
6
|
+
* @returns Processed configuration object with resolved element references
|
|
7
|
+
*/
|
|
8
|
+
export function resolveEditorConfigElementReferences<T>(obj: T): T {
|
|
9
|
+
if (!obj || typeof obj !== 'object') {
|
|
10
|
+
return obj;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (Array.isArray(obj)) {
|
|
14
|
+
return obj.map(item => resolveEditorConfigElementReferences(item)) as T;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const anyObj = obj as any;
|
|
18
|
+
|
|
19
|
+
if (anyObj.$element && typeof anyObj.$element === 'string') {
|
|
20
|
+
const element = document.querySelector(anyObj.$element);
|
|
21
|
+
|
|
22
|
+
if (!element) {
|
|
23
|
+
console.warn(`Element not found for selector: ${anyObj.$element}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (element || null) as T;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = Object.create(null);
|
|
30
|
+
|
|
31
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
32
|
+
result[key] = resolveEditorConfigElementReferences(value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return result as T;
|
|
36
|
+
}
|