@ckeditor/ckeditor5-dev-manual-server 60.0.0 → 61.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/README.md CHANGED
@@ -10,8 +10,8 @@ More information about development tools packages can be found at the following
10
10
 
11
11
  ## Loading translations
12
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.
13
+ Pass a language code to `manualTestsPlugin()` to load and combine that language's TypeScript translation files from the configured package paths. The selected language becomes the default UI and content language for editors and contexts created by manual tests.
14
+
15
15
  An explicit language in an editor or context configuration still takes precedence.
16
16
 
17
17
  ```ts
@@ -23,6 +23,29 @@ manualTestsPlugin( {
23
23
 
24
24
  For example, start the manual test server in Polish using `CK_LANGUAGE=pl pnpm manual`.
25
25
 
26
+ ## Preserving production CSS order
27
+
28
+ Vite may order extracted stylesheets differently from their source imports in multi-page production builds. Add `preserveCssImportOrderPlugin()` to keep the CSS cascade consistent with the bundled development server:
29
+
30
+ ```ts
31
+ import { defineConfig } from 'vite';
32
+ import {
33
+ manualTestsPlugin,
34
+ preserveCssImportOrderPlugin
35
+ } from '@ckeditor/ckeditor5-dev-manual-server';
36
+
37
+ export default defineConfig( {
38
+ plugins: [
39
+ preserveCssImportOrderPlugin(),
40
+ manualTestsPlugin( {
41
+ paths: [ 'packages/*' ]
42
+ } )
43
+ ]
44
+ } );
45
+ ```
46
+
47
+ The plugin enables Rolldown's strict module execution order in development and production, which can increase the generated bundle size. During production builds, it additionally rewrites plain CSS imports into ordered JavaScript side effects.
48
+
26
49
  ## Changelog
27
50
 
28
51
  See the [`CHANGELOG.md`](https://github.com/ckeditor/ckeditor5-dev/blob/master/packages/ckeditor5-dev-manual-server/CHANGELOG.md) file.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * For licensing, see LICENSE.md.
4
4
  */
5
5
  export { manualTestsPlugin, type ManualTestsPluginOptions } from "./manual-test-plugin/plugin.js";
6
+ export { preserveCssImportOrderPlugin } from "./preserve-css-import-order-plugin/plugin.js";
6
7
  export { ckDebugPlugin } from "./debug-plugin/plugin.js";
7
8
  export { refreshPlugin } from "./refresh-plugin/plugin.js";
8
9
  export { rawSvgPlugin } from "./svg-plugin/plugin.js";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { existsSync, globSync, readFileSync, realpathSync } from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { basename, isAbsolute, posix, relative, resolve } from "node:path";
4
+ import { createHash } from "node:crypto";
4
5
  //#region src/utils.ts
5
6
  /**
6
7
  * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
@@ -371,6 +372,78 @@ function parseRequestUrl(requestUrl) {
371
372
  return URL.parse(requestUrl || "", "http://localhost");
372
373
  }
373
374
  //#endregion
375
+ //#region src/preserve-css-import-order-plugin/plugin.ts
376
+ /**
377
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
378
+ * For licensing, see LICENSE.md.
379
+ */
380
+ const INJECTED_CSS_VIRTUAL_ID_PREFIX = "\0virtual:ckeditor5-preserve-css-import-order:";
381
+ const INJECTED_CSS_VIRTUAL_ID_SUFFIX = ".js";
382
+ const CSS_FILE_REGEXP = /^[^?#]+\.css$/;
383
+ /**
384
+ * Preserves the source execution order of CSS imports in manual development and production builds.
385
+ *
386
+ * Vite extracts imported CSS into assets and orders those assets by the generated chunk graph.
387
+ * In a multi-page build that order may differ from the source module execution order, changing
388
+ * the cascade between CKEditor stylesheets. This is a known Vite limitation:
389
+ * https://github.com/vitejs/vite/issues/4890.
390
+ *
391
+ * Until Vite handles this natively (https://github.com/vitejs/vite/pull/22541), plain CSS imports
392
+ * in production builds are replaced with virtual JavaScript modules. Each module loads the
393
+ * processed CSS through Vite's `?inline` query and appends it as a `<style>` side effect.
394
+ * Rolldown's `strictExecutionOrder` keeps both these production effects and Vite's native bundled
395
+ * development CSS effects in source order.
396
+ *
397
+ * Query-bearing CSS imports retain their explicit Vite semantics and pass through unchanged.
398
+ */
399
+ function preserveCssImportOrderPlugin() {
400
+ let rewriteCssImports = false;
401
+ const cssFilePaths = /* @__PURE__ */ new Map();
402
+ return {
403
+ name: "ckeditor5-preserve-css-import-order",
404
+ config(_config, { command }) {
405
+ rewriteCssImports = command == "build";
406
+ return { build: { rolldownOptions: { output: { strictExecutionOrder: true } } } };
407
+ },
408
+ resolveId: {
409
+ order: "pre",
410
+ filter: { id: CSS_FILE_REGEXP },
411
+ async handler(source, importer, options) {
412
+ if (!rewriteCssImports) return null;
413
+ const resolved = await this.resolve(source, importer, {
414
+ ...options,
415
+ skipSelf: true
416
+ });
417
+ if (!resolved || resolved.external) return null;
418
+ const cssIdHash = createHash("sha256").update(resolved.id).digest("hex");
419
+ const virtualId = `${INJECTED_CSS_VIRTUAL_ID_PREFIX}${cssIdHash}${INJECTED_CSS_VIRTUAL_ID_SUFFIX}`;
420
+ cssFilePaths.set(virtualId, resolved.id);
421
+ return virtualId;
422
+ }
423
+ },
424
+ load: {
425
+ filter: { id: new RegExp(`^${INJECTED_CSS_VIRTUAL_ID_PREFIX}`) },
426
+ handler(id) {
427
+ const cssFilePath = cssFilePaths.get(id);
428
+ if (!cssFilePath) return null;
429
+ return {
430
+ code: createCssInjectionModule(cssFilePath),
431
+ moduleSideEffects: true
432
+ };
433
+ }
434
+ }
435
+ };
436
+ }
437
+ function createCssInjectionModule(cssFilePath) {
438
+ return `
439
+ import css from ${JSON.stringify(`${cssFilePath}?inline`)};
440
+
441
+ const style = document.createElement( 'style' );
442
+ style.textContent = css;
443
+ document.head.appendChild( style );
444
+ `;
445
+ }
446
+ //#endregion
374
447
  //#region src/debug-plugin/plugin.ts
375
448
  /**
376
449
  * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
@@ -524,4 +597,4 @@ function rawSvgPlugin() {
524
597
  * For licensing, see LICENSE.md.
525
598
  */
526
599
  //#endregion
527
- export { ckDebugPlugin, manualTestsPlugin, rawSvgPlugin, refreshPlugin, stringifyValues };
600
+ export { ckDebugPlugin, manualTestsPlugin, preserveCssImportOrderPlugin, rawSvgPlugin, refreshPlugin, stringifyValues };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md.
4
+ */
5
+ import type { Plugin } from "vite";
6
+ /**
7
+ * Preserves the source execution order of CSS imports in manual development and production builds.
8
+ *
9
+ * Vite extracts imported CSS into assets and orders those assets by the generated chunk graph.
10
+ * In a multi-page build that order may differ from the source module execution order, changing
11
+ * the cascade between CKEditor stylesheets. This is a known Vite limitation:
12
+ * https://github.com/vitejs/vite/issues/4890.
13
+ *
14
+ * Until Vite handles this natively (https://github.com/vitejs/vite/pull/22541), plain CSS imports
15
+ * in production builds are replaced with virtual JavaScript modules. Each module loads the
16
+ * processed CSS through Vite's `?inline` query and appends it as a `<style>` side effect.
17
+ * Rolldown's `strictExecutionOrder` keeps both these production effects and Vite's native bundled
18
+ * development CSS effects in source order.
19
+ *
20
+ * Query-bearing CSS imports retain their explicit Vite semantics and pass through unchanged.
21
+ */
22
+ export declare function preserveCssImportOrderPlugin(): Plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-dev-manual-server",
3
- "version": "60.0.0",
3
+ "version": "61.1.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/)",