@ckeditor/ckeditor5-dev-manual-server 59.1.0 → 61.0.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/README.md +15 -0
- package/dist/index.js +89 -43
- package/dist/manual-test-plugin/plugin.d.ts +1 -0
- package/dist/manual-test-plugin/translations.d.ts +10 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,6 +8,21 @@ Used to extend Vite to create a manual test server for CKEditor 5.
|
|
|
8
8
|
|
|
9
9
|
More information about development tools packages can be found at the following URL: <https://github.com/ckeditor/ckeditor5-dev>.
|
|
10
10
|
|
|
11
|
+
## Loading translations
|
|
12
|
+
|
|
13
|
+
Pass a language code to `manualTestsPlugin()` to load and combine that language's TypeScript translation files from the configured
|
|
14
|
+
package paths. The selected language becomes the default UI and content language for editors and contexts created by manual tests.
|
|
15
|
+
An explicit language in an editor or context configuration still takes precedence.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
manualTestsPlugin( {
|
|
19
|
+
paths: [ 'packages/*' ],
|
|
20
|
+
language: process.env.CK_LANGUAGE || 'en'
|
|
21
|
+
} )
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For example, start the manual test server in Polish using `CK_LANGUAGE=pl pnpm manual`.
|
|
25
|
+
|
|
11
26
|
## Changelog
|
|
12
27
|
|
|
13
28
|
See the [`CHANGELOG.md`](https://github.com/ckeditor/ckeditor5-dev/blob/master/packages/ckeditor5-dev-manual-server/CHANGELOG.md) file.
|
package/dist/index.js
CHANGED
|
@@ -88,6 +88,47 @@ function toManualPageEntry(relativeFilePath, workspaceRoot) {
|
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
//#endregion
|
|
91
|
+
//#region src/manual-test-plugin/translations.ts
|
|
92
|
+
/**
|
|
93
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
94
|
+
* For licensing, see LICENSE.md.
|
|
95
|
+
*/
|
|
96
|
+
const MANUAL_TRANSLATIONS_VIRTUAL_ID = "virtual:ckeditor5-manual-translations";
|
|
97
|
+
const RESOLVED_MANUAL_TRANSLATIONS_VIRTUAL_ID = `\0${MANUAL_TRANSLATIONS_VIRTUAL_ID}`;
|
|
98
|
+
/**
|
|
99
|
+
* Generates the virtual module that loads translations from every configured package root.
|
|
100
|
+
*/
|
|
101
|
+
function createManualTranslationsModule(paths, language) {
|
|
102
|
+
const translationPatterns = paths.map((packagePath) => {
|
|
103
|
+
return posix.join("/", toPosixPath(packagePath), `lang/translations/${language}.ts`);
|
|
104
|
+
});
|
|
105
|
+
return `
|
|
106
|
+
import { add } from '@ckeditor/ckeditor5-utils';
|
|
107
|
+
import { Context, Editor } from '@ckeditor/ckeditor5-core';
|
|
108
|
+
|
|
109
|
+
const translationModules = import.meta.glob(
|
|
110
|
+
${JSON.stringify(translationPatterns)},
|
|
111
|
+
{ eager: true, import: 'default' }
|
|
112
|
+
);
|
|
113
|
+
const language = ${JSON.stringify(language)};
|
|
114
|
+
const translations = Object.values( translationModules ).map( module => module[ language ] );
|
|
115
|
+
|
|
116
|
+
if ( !translations.length ) {
|
|
117
|
+
throw new Error( \`No CKEditor 5 translations found for "\${ language }".\` );
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if ( !translations.some( translation => translation.getPluralForm ) ) {
|
|
121
|
+
throw new Error( \`The ckeditor5-core translations for "\${ language }" were not loaded.\` );
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for ( const translation of translations ) {
|
|
125
|
+
add( language, translation.dictionary, translation.getPluralForm );
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
Editor.defaultConfig = { ...Editor.defaultConfig, language: ${JSON.stringify(language)} };
|
|
129
|
+
Context.defaultConfig = { ...Context.defaultConfig, language: ${JSON.stringify(language)} };`;
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
91
132
|
//#region src/manual-test-plugin/plugin.ts
|
|
92
133
|
/**
|
|
93
134
|
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
@@ -137,33 +178,38 @@ function manualTestsPlugin(options) {
|
|
|
137
178
|
slug: entry.slug
|
|
138
179
|
}));
|
|
139
180
|
const getManualEntriesJson = () => JSON.stringify(getClientEntries(), null, 2);
|
|
181
|
+
const translationsModuleCode = options.language ? createManualTranslationsModule(options.paths, options.language) : null;
|
|
140
182
|
return {
|
|
141
183
|
name: "ckeditor5-manual-tests",
|
|
142
|
-
config() {
|
|
143
|
-
|
|
184
|
+
config(config = {}) {
|
|
185
|
+
workspaceRoot = resolve(config.root || process.cwd());
|
|
186
|
+
return {
|
|
187
|
+
input: getManualBuildInputs(),
|
|
188
|
+
build: { rolldownOptions: { output: { strictExecutionOrder: true } } }
|
|
189
|
+
};
|
|
144
190
|
},
|
|
145
191
|
configResolved(config) {
|
|
146
192
|
workspaceRoot = config.root;
|
|
147
193
|
base = config.base || "/";
|
|
148
194
|
manualPagesCache.invalidate();
|
|
149
195
|
packageThemeEntryCache.clear();
|
|
150
|
-
config.build.rolldownOptions.input = getManualBuildInputs();
|
|
151
196
|
},
|
|
152
197
|
configureServer(server) {
|
|
153
198
|
server.middlewares.use((request, _response, next) => {
|
|
154
199
|
rewriteCatalogRequest(request, getManualCatalogPublicPath());
|
|
155
200
|
next();
|
|
156
201
|
});
|
|
157
|
-
|
|
158
|
-
keepManualHtmlSourceFresh(clientEnvironment.bundledDev?.memoryFiles, getManualPages, workspaceRoot);
|
|
202
|
+
keepManualHtmlSourceFresh(server.environments.client.bundledDev?.memoryFiles, getManualPages, workspaceRoot);
|
|
159
203
|
},
|
|
160
204
|
resolveId(source) {
|
|
161
205
|
if (source == MANUAL_ENTRIES_VIRTUAL_ID) return resolvedVirtualModuleId;
|
|
206
|
+
if (source == "virtual:ckeditor5-manual-translations" && translationsModuleCode) return RESOLVED_MANUAL_TRANSLATIONS_VIRTUAL_ID;
|
|
162
207
|
if (isManualCatalogBuildInputSpecifier(source, getManualCatalogBuildInputFilePath(), workspaceRoot)) return getManualCatalogBuildInputFilePath();
|
|
163
208
|
return null;
|
|
164
209
|
},
|
|
165
210
|
load(id) {
|
|
166
211
|
if (id == resolvedVirtualModuleId) return `export const manualTestEntries = ${getManualEntriesJson()};`;
|
|
212
|
+
if (id == RESOLVED_MANUAL_TRANSLATIONS_VIRTUAL_ID) return translationsModuleCode;
|
|
167
213
|
if (toPosixPath(id) == toPosixPath(getManualCatalogBuildInputFilePath())) return readFileSync(MANUAL_CATALOG_FILE_PATH, "utf8");
|
|
168
214
|
return null;
|
|
169
215
|
},
|
|
@@ -174,12 +220,13 @@ function manualTestsPlugin(options) {
|
|
|
174
220
|
const entry = getManualPageEntryForScriptSpecifier(scriptSpecifier);
|
|
175
221
|
if (!entry) return;
|
|
176
222
|
const packageRootSpecifier = entry.htmlFilePath.slice(0, entry.htmlFilePath.indexOf(MANUAL_TESTS_DIRECTORY));
|
|
177
|
-
const
|
|
178
|
-
|
|
223
|
+
const imports = getPackageThemeEntries(packageRootSpecifier).map((themeEntryFilePath) => {
|
|
224
|
+
return `import '${posix.relative(posix.dirname(scriptSpecifier), `${packageRootSpecifier}/${themeEntryFilePath}`)}';`;
|
|
225
|
+
});
|
|
226
|
+
if (options.language) imports.push(`import '${MANUAL_TRANSLATIONS_VIRTUAL_ID}';`);
|
|
227
|
+
if (!imports.length) return;
|
|
179
228
|
return {
|
|
180
|
-
code: `${code}\n${
|
|
181
|
-
return `import '${posix.relative(posix.dirname(scriptSpecifier), `${packageRootSpecifier}/${themeEntryFilePath}`)}';`;
|
|
182
|
-
}).join("\n")}\n`,
|
|
229
|
+
code: `${code}\n${imports.join("\n")}\n`,
|
|
183
230
|
map: null
|
|
184
231
|
};
|
|
185
232
|
}
|
|
@@ -207,7 +254,7 @@ function manualTestsPlugin(options) {
|
|
|
207
254
|
* produced by the rolldown dev engine. That engine emits the HTML output only during the initial
|
|
208
255
|
* build and never regenerates it when the source `.html` changes: its bundle state reports no
|
|
209
256
|
* stale output for HTML entries, `devEngine.invalidate()` throws on a non-JS module, and even a
|
|
210
|
-
* forced full build leaves the HTML memory file untouched (verified against Vite 8.1
|
|
257
|
+
* forced full build leaves the HTML memory file untouched (verified against Vite 8.2.1). A `.html`
|
|
211
258
|
* edit still triggers a full page reload, so without this the browser reloads into the same stale
|
|
212
259
|
* HTML until the server is restarted.
|
|
213
260
|
*
|
|
@@ -368,39 +415,40 @@ function getDebugFlags(debugOption = "") {
|
|
|
368
415
|
* For licensing, see LICENSE.md.
|
|
369
416
|
*/
|
|
370
417
|
const MANUAL_REFRESH_EVENT_NAME = "ckeditor5-manual:refresh-available";
|
|
371
|
-
const
|
|
418
|
+
const wrappedClients = /* @__PURE__ */ new WeakSet();
|
|
372
419
|
function refreshPlugin() {
|
|
373
420
|
return {
|
|
374
421
|
name: "ckeditor5-manual-refresh",
|
|
375
422
|
apply: "serve",
|
|
376
423
|
configureServer(server) {
|
|
377
|
-
const bundledDev = server.environments.client
|
|
378
|
-
|
|
379
|
-
wrapBundledDevClientSend(bundledDev.clients);
|
|
424
|
+
const { bundledDev } = server.environments.client;
|
|
425
|
+
wrapBundledDevClientSend(bundledDev);
|
|
380
426
|
wrapBundledDevFullReloads(bundledDev, server.config.root);
|
|
427
|
+
},
|
|
428
|
+
hotUpdate({ file, modules }) {
|
|
429
|
+
if (file.endsWith(".manual.html")) return modules;
|
|
381
430
|
}
|
|
382
431
|
};
|
|
383
432
|
}
|
|
384
|
-
function wrapBundledDevClientSend(
|
|
385
|
-
|
|
433
|
+
function wrapBundledDevClientSend(bundledDev) {
|
|
434
|
+
const clients = bundledDev.clients;
|
|
386
435
|
const setupIfNeeded = clients.setupIfNeeded.bind(clients);
|
|
387
436
|
clients.setupIfNeeded = (client, clientId) => {
|
|
388
|
-
if (!client
|
|
437
|
+
if (!wrappedClients.has(client)) {
|
|
389
438
|
const send = client.send.bind(client);
|
|
390
439
|
client.send = (payload) => {
|
|
391
|
-
sendManualRefreshPayload(payload, send);
|
|
440
|
+
sendManualRefreshPayload(bundledDev, payload, send);
|
|
392
441
|
};
|
|
393
|
-
client
|
|
442
|
+
wrappedClients.add(client);
|
|
394
443
|
}
|
|
395
444
|
return setupIfNeeded(client, clientId);
|
|
396
445
|
};
|
|
397
446
|
}
|
|
398
447
|
function wrapBundledDevFullReloads(bundledDev, workspaceRoot) {
|
|
399
|
-
if (typeof bundledDev.handleHmrOutput != "function") return;
|
|
400
448
|
const handleHmrOutput = bundledDev.handleHmrOutput.bind(bundledDev);
|
|
401
|
-
bundledDev.handleHmrOutput = (client, files, hmrOutput
|
|
402
|
-
if (hmrOutput.type != "FullReload") return handleHmrOutput(client, files, hmrOutput
|
|
403
|
-
if (!
|
|
449
|
+
bundledDev.handleHmrOutput = (client, files, hmrOutput) => {
|
|
450
|
+
if (hmrOutput.type != "FullReload") return handleHmrOutput(client, files, hmrOutput);
|
|
451
|
+
if (!shouldShowManualRefreshPrompt(files)) {
|
|
404
452
|
reloadClientAfterLatestBuildOutput(bundledDev, client, files, workspaceRoot);
|
|
405
453
|
return;
|
|
406
454
|
}
|
|
@@ -413,25 +461,26 @@ function wrapBundledDevFullReloads(bundledDev, workspaceRoot) {
|
|
|
413
461
|
}
|
|
414
462
|
async function reloadClientAfterLatestBuildOutput(bundledDev, client, files, workspaceRoot) {
|
|
415
463
|
try {
|
|
416
|
-
await bundledDev.devEngine
|
|
464
|
+
await bundledDev.devEngine.ensureLatestBuildOutput();
|
|
417
465
|
} catch {}
|
|
466
|
+
const htmlFile = files.find((file) => isHtmlFile(file));
|
|
418
467
|
client.send({
|
|
419
468
|
type: "full-reload",
|
|
420
|
-
path:
|
|
469
|
+
path: htmlFile ? toPublicFilePath(htmlFile, workspaceRoot) : void 0
|
|
421
470
|
});
|
|
422
471
|
}
|
|
423
|
-
function getChangedHtmlPublicPath(files, workspaceRoot) {
|
|
424
|
-
const htmlFile = files.find((file) => file.endsWith(".html"));
|
|
425
|
-
return htmlFile ? toPublicFilePath(htmlFile, workspaceRoot) : void 0;
|
|
426
|
-
}
|
|
427
472
|
function ensureLatestBuildOutput(bundledDev) {
|
|
428
473
|
try {
|
|
429
|
-
bundledDev.devEngine
|
|
474
|
+
bundledDev.devEngine.ensureLatestBuildOutput().catch(() => {});
|
|
430
475
|
} catch {}
|
|
431
476
|
}
|
|
432
|
-
function sendManualRefreshPayload(payload, send) {
|
|
433
|
-
if (payload.type == "update" &&
|
|
434
|
-
|
|
477
|
+
function sendManualRefreshPayload(bundledDev, payload, send) {
|
|
478
|
+
if (payload.type == "bundled-dev-update" && shouldShowManualRefreshPrompt(payload.changedIds)) {
|
|
479
|
+
ensureLatestBuildOutput(bundledDev);
|
|
480
|
+
send({
|
|
481
|
+
...payload,
|
|
482
|
+
changedIds: []
|
|
483
|
+
});
|
|
435
484
|
send({
|
|
436
485
|
type: "custom",
|
|
437
486
|
event: MANUAL_REFRESH_EVENT_NAME
|
|
@@ -440,17 +489,14 @@ function sendManualRefreshPayload(payload, send) {
|
|
|
440
489
|
}
|
|
441
490
|
send(payload);
|
|
442
491
|
}
|
|
443
|
-
function shouldShowManualRefreshPrompt(
|
|
444
|
-
|
|
445
|
-
return false;
|
|
492
|
+
function shouldShowManualRefreshPrompt(filePaths) {
|
|
493
|
+
return filePaths.some((filePath) => !isCssFile(filePath) && !isHtmlFile(filePath));
|
|
446
494
|
}
|
|
447
|
-
function
|
|
448
|
-
return
|
|
449
|
-
return update.type == "css-update" || update.type == "js-update" && update.acceptedPath.endsWith(".css");
|
|
450
|
-
});
|
|
495
|
+
function isCssFile(filePath) {
|
|
496
|
+
return filePath.split("?", 1)[0].endsWith(".css");
|
|
451
497
|
}
|
|
452
|
-
function
|
|
453
|
-
return
|
|
498
|
+
function isHtmlFile(filePath) {
|
|
499
|
+
return filePath.split("?", 1)[0].endsWith(".html");
|
|
454
500
|
}
|
|
455
501
|
//#endregion
|
|
456
502
|
//#region src/svg-plugin/plugin.ts
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
export declare const MANUAL_TRANSLATIONS_VIRTUAL_ID: string;
|
|
6
|
+
export declare const RESOLVED_MANUAL_TRANSLATIONS_VIRTUAL_ID: string;
|
|
7
|
+
/**
|
|
8
|
+
* Generates the virtual module that loads translations from every configured package root.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createManualTranslationsModule(paths: Array<string>, language: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-dev-manual-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "61.0.0",
|
|
4
4
|
"description": "Used to extend Vite to create a manual test server for CKEditor 5.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "CKSource (http://cksource.com/)",
|
|
@@ -25,6 +25,6 @@
|
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@ckeditor/ckeditor5-inspector": "^5.0.1",
|
|
28
|
-
"vite": "^8.1
|
|
28
|
+
"vite": "^8.2.1"
|
|
29
29
|
}
|
|
30
30
|
}
|