@ws-ui/vite-plugins 1.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.
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from 'esbuild';
2
+ declare const importMetaUrlPlugin: Plugin;
3
+ export default importMetaUrlPlugin;
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { pathToFileURL, fileURLToPath } from 'node:url';
3
+ import { resolve } from 'import-meta-resolve';
4
+ const importMetaUrlPlugin = {
5
+ name: 'import.meta.url',
6
+ setup({ onLoad }) {
7
+ // Help vite that bundles/move files in dev mode without touching `import.meta.url` which breaks asset urls
8
+ onLoad({ filter: /.*\.js/, namespace: 'file' }, async (args) => {
9
+ if (/node_modules(\/|\\)(mime-types|mime-db)/.test(args.path)) {
10
+ return;
11
+ }
12
+ const code = readFileSync(args.path, 'utf8');
13
+ const assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/g;
14
+ let i = 0;
15
+ let newCode = '';
16
+ for (let match = assetImportMetaUrlRE.exec(code); match != null; match = assetImportMetaUrlRE.exec(code)) {
17
+ newCode += code.slice(i, match.index);
18
+ const path = match[1].slice(1, -1);
19
+ const resolved = resolve(path, pathToFileURL(args.path).toString());
20
+ newCode += `new URL(${JSON.stringify(fileURLToPath(resolved))}, import.meta.url)`;
21
+ i = assetImportMetaUrlRE.lastIndex;
22
+ }
23
+ newCode += code.slice(i);
24
+ return { contents: newCode };
25
+ });
26
+ },
27
+ };
28
+ export default importMetaUrlPlugin;
@@ -0,0 +1,3 @@
1
+ import importMetaUrlPlugin from './esbuild-plugin-import-meta-url';
2
+ import monacoEditorPlugin from './vite-plugin-monaco-editor';
3
+ export { importMetaUrlPlugin, monacoEditorPlugin };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import importMetaUrlPlugin from './esbuild-plugin-import-meta-url';
2
+ import monacoEditorPlugin from './vite-plugin-monaco-editor';
3
+ export { importMetaUrlPlugin, monacoEditorPlugin };
@@ -0,0 +1,3 @@
1
+ import { Plugin } from 'vite';
2
+ import { IMonacoEditorOpts } from './types';
3
+ export default function monacoEditorPlugin(options?: IMonacoEditorOpts): Plugin;
@@ -0,0 +1,98 @@
1
+ import esbuild from 'esbuild';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { languageWorksByLabel } from './languageWork';
5
+ import { workerMiddleware, cacheDir, getFilename, getWorkPath, } from './workerMiddleware';
6
+ import { getWorks, isCDN, resolveMonacoPath } from './utils';
7
+ export default function monacoEditorPlugin(options = {}) {
8
+ const languageWorkers = options.languageWorkers ||
9
+ Object.keys(languageWorksByLabel);
10
+ const publicPath = options.publicPath || 'assets';
11
+ const globalAPI = options.globalAPI || false;
12
+ const customWorkers = options.customWorkers || [];
13
+ const forceBuildCDN = options.forceBuildCDN || false;
14
+ options = {
15
+ ...options,
16
+ languageWorkers,
17
+ publicPath,
18
+ globalAPI,
19
+ customWorkers,
20
+ forceBuildCDN,
21
+ };
22
+ let resolvedConfig;
23
+ return {
24
+ name: 'vite-plugin-monaco-editor',
25
+ configResolved(getResolvedConfig) {
26
+ resolvedConfig = getResolvedConfig;
27
+ },
28
+ configureServer(server) {
29
+ if (isCDN(publicPath)) {
30
+ return;
31
+ }
32
+ workerMiddleware(server.middlewares, resolvedConfig, options);
33
+ },
34
+ transformIndexHtml(_html) {
35
+ const works = getWorks(options);
36
+ const workerPaths = getWorkPath(works, options, resolvedConfig);
37
+ const globals = {
38
+ MonacoEnvironment: `(function (paths) {
39
+ return {
40
+ globalAPI: ${globalAPI},
41
+ getWorkerUrl : function (moduleId, label) {
42
+ var result = paths[label];
43
+ if (/^((http:)|(https:)|(file:)|(\\/\\/))/.test(result)) {
44
+ var currentUrl = String(window.location);
45
+ var currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length);
46
+ if (result.substring(0, currentOrigin.length) !== currentOrigin) {
47
+ var js = '/*' + label + '*/importScripts("' + result + '");';
48
+ var blob = new Blob([js], { type: 'application/javascript' });
49
+ return URL.createObjectURL(blob);
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ };
55
+ })(${JSON.stringify(workerPaths, null, 2)})`,
56
+ };
57
+ const descriptor = [
58
+ {
59
+ tag: 'script',
60
+ children: Object.keys(globals)
61
+ .map((key) => `self[${JSON.stringify(key)}] = ${globals[key]};`)
62
+ .join('\n'),
63
+ injectTo: 'head-prepend',
64
+ },
65
+ ];
66
+ return descriptor;
67
+ },
68
+ writeBundle() {
69
+ if (isCDN(publicPath) && !forceBuildCDN) {
70
+ return;
71
+ }
72
+ const works = getWorks(options);
73
+ const distPath = options.customDistPath
74
+ ? options.customDistPath(resolvedConfig.root, resolvedConfig.build.outDir, resolvedConfig.base)
75
+ : path.join(resolvedConfig.root, resolvedConfig.build.outDir, resolvedConfig.base, options.publicPath || '');
76
+ // console.log("distPath", distPath)
77
+ // write publicPath
78
+ if (!fs.existsSync(distPath)) {
79
+ fs.mkdirSync(distPath, {
80
+ recursive: true,
81
+ });
82
+ }
83
+ for (const work of works) {
84
+ const filename = getFilename(work);
85
+ if (!fs.existsSync(cacheDir + filename)) {
86
+ esbuild.buildSync({
87
+ entryPoints: [resolveMonacoPath(work.entry)],
88
+ bundle: true,
89
+ outfile: cacheDir + filename,
90
+ });
91
+ }
92
+ const contentBuffer = fs.readFileSync(cacheDir + filename);
93
+ const workDistPath = path.resolve(distPath, filename);
94
+ fs.writeFileSync(workDistPath, contentBuffer);
95
+ }
96
+ },
97
+ };
98
+ }
@@ -0,0 +1,6 @@
1
+ import { IWorkerDefinition } from './types';
2
+ export declare const languageWorkAttr: IWorkerDefinition[];
3
+ declare const languageWorksByLabel: {
4
+ [language: string]: IWorkerDefinition;
5
+ };
6
+ export { languageWorksByLabel };
@@ -0,0 +1,35 @@
1
+ export const languageWorkAttr = [
2
+ {
3
+ label: 'editorWorkerService',
4
+ filename: 'editor.worker.bundle.js',
5
+ entry: 'monaco-editor/esm/vs/editor/editor.worker',
6
+ },
7
+ {
8
+ label: 'textMateWorker',
9
+ filename: 'textmate.worker.bundle.js',
10
+ entry: '@codingame/monaco-vscode-textmate-service-override/worker?worker',
11
+ },
12
+ {
13
+ label: 'css',
14
+ filename: 'css.worker.bundle.js',
15
+ entry: '@codingame/monaco-vscode-standalone-css-language-features/worker',
16
+ },
17
+ {
18
+ label: 'html',
19
+ filename: 'html.worker.bundle.js',
20
+ entry: '@codingame/monaco-vscode-standalone-html-language-features/worker',
21
+ },
22
+ {
23
+ label: 'json',
24
+ filename: 'json.worker.bundle.js',
25
+ entry: '@codingame/monaco-vscode-standalone-json-language-features/worker',
26
+ },
27
+ {
28
+ label: 'typescript',
29
+ filename: 'ts.worker.bundle.js',
30
+ entry: '@codingame/monaco-vscode-standalone-typescript-language-features/worker',
31
+ },
32
+ ];
33
+ const languageWorksByLabel = {};
34
+ languageWorkAttr.forEach((languageWork) => (languageWorksByLabel[languageWork.label] = languageWork));
35
+ export { languageWorksByLabel };
@@ -0,0 +1,30 @@
1
+ export interface IWorkerDefinition {
2
+ label: string;
3
+ filename?: string;
4
+ entry: string;
5
+ }
6
+ export type EditorLanguageWorks = 'css' | 'html' | 'json' | 'typescript' | 'editorWorkerService';
7
+ export interface IMonacoEditorOpts {
8
+ /**
9
+ * include only a subset of the languageWorkers supported.
10
+ */
11
+ languageWorkers?: EditorLanguageWorks[];
12
+ customWorkers?: IWorkerDefinition[];
13
+ /**
14
+ * Override the public path from which files generated by this plugin will be served.
15
+ * This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-
16
+ * origin when using a CDN for other static resources.
17
+ * Use e.g. '/' if you want to load your resources from the current origin.
18
+ */
19
+ publicPath?: string;
20
+ customDistPath?: (root: string, buildOutDir: string, base: string) => string;
21
+ forceBuildCDN?: boolean;
22
+ /**
23
+ * Specify whether the editor API should be exposed through a global `monaco` object or not. This
24
+ * option is applicable to `0.22.0` and newer version of `monaco-editor`. Since `0.22.0`, the ESM
25
+ * version of the monaco editor does no longer define a global `monaco` object unless
26
+ * `global.MonacoEnvironment = { globalAPI: true }` is set ([change
27
+ * log](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md#0220-29012021)).
28
+ */
29
+ globalAPI?: boolean;
30
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import { IMonacoEditorOpts, IWorkerDefinition } from './types';
2
+ /**
3
+ * Return a resolved path for a given Monaco file.
4
+ */
5
+ export declare function resolveMonacoPath(filePath: string): string;
6
+ export declare function getWorks(options: IMonacoEditorOpts): IWorkerDefinition[];
7
+ export declare function isCDN(publicPath: string): boolean;
@@ -0,0 +1,26 @@
1
+ import * as path from 'path';
2
+ import { languageWorksByLabel } from './languageWork';
3
+ /**
4
+ * Return a resolved path for a given Monaco file.
5
+ */
6
+ export function resolveMonacoPath(filePath) {
7
+ try {
8
+ return path.resolve(path.join(process.cwd(), 'node_modules', filePath));
9
+ }
10
+ catch (err) {
11
+ return path.resolve(filePath);
12
+ }
13
+ }
14
+ export function getWorks(options) {
15
+ let works = (options.languageWorkers || [])
16
+ .map((work) => languageWorksByLabel[work])
17
+ .filter(Boolean);
18
+ works.push(...(options.customWorkers || []));
19
+ return works;
20
+ }
21
+ export function isCDN(publicPath) {
22
+ if (/^((http:)|(https:)|(file:)|(\/\/))/.test(publicPath)) {
23
+ return true;
24
+ }
25
+ return false;
26
+ }
@@ -0,0 +1,9 @@
1
+ import { Connect, ResolvedConfig } from 'vite';
2
+ import { IMonacoEditorOpts, IWorkerDefinition } from './types';
3
+ export declare function getFilenameByEntry(entry: string): string;
4
+ export declare function getFilename(work: IWorkerDefinition): string;
5
+ export declare const cacheDir = "node_modules/.monaco/";
6
+ export declare function getWorkPath(works: IWorkerDefinition[], options: IMonacoEditorOpts, config: ResolvedConfig): {
7
+ [key: string]: string;
8
+ };
9
+ export declare function workerMiddleware(middlewares: Connect.Server, config: ResolvedConfig, options: IMonacoEditorOpts): void;
@@ -0,0 +1,63 @@
1
+ import { getWorks, isCDN, resolveMonacoPath } from './utils';
2
+ import esbuild from 'esbuild';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ export function getFilenameByEntry(entry) {
6
+ entry = path.basename(entry, 'js');
7
+ return entry + '.bundle.js';
8
+ }
9
+ export function getFilename(work) {
10
+ return work.filename || getFilenameByEntry(work.entry);
11
+ }
12
+ export const cacheDir = 'node_modules/.monaco/';
13
+ export function getWorkPath(works, options, config) {
14
+ const workerPaths = {};
15
+ for (const work of works) {
16
+ const filename = getFilename(work);
17
+ if (options.publicPath && isCDN(options.publicPath)) {
18
+ workerPaths[work.label] =
19
+ options.publicPath + '/' + filename;
20
+ }
21
+ else {
22
+ workerPaths[work.label] =
23
+ config.base + options.publicPath + '/' + filename;
24
+ }
25
+ }
26
+ if (workerPaths['typescript']) {
27
+ // javascript shares the same worker
28
+ workerPaths['javascript'] = workerPaths['typescript'];
29
+ }
30
+ if (workerPaths['css']) {
31
+ // scss and less share the same worker
32
+ workerPaths['less'] = workerPaths['css'];
33
+ workerPaths['scss'] = workerPaths['css'];
34
+ }
35
+ if (workerPaths['html']) {
36
+ // handlebars, razor and html share the same worker
37
+ workerPaths['handlebars'] = workerPaths['html'];
38
+ workerPaths['razor'] = workerPaths['html'];
39
+ }
40
+ return workerPaths;
41
+ }
42
+ export function workerMiddleware(middlewares, config, options) {
43
+ const works = getWorks(options);
44
+ // clear cacheDir
45
+ if (fs.existsSync(cacheDir)) {
46
+ fs.rmdirSync(cacheDir, { recursive: true, force: true });
47
+ }
48
+ for (const work of works) {
49
+ const filename = getFilename(work);
50
+ middlewares.use(config.base + options.publicPath + '/' + filename, function (_req, res, _next) {
51
+ if (!fs.existsSync(cacheDir + filename)) {
52
+ esbuild.buildSync({
53
+ entryPoints: [resolveMonacoPath(work.entry)],
54
+ bundle: true,
55
+ outfile: cacheDir + filename,
56
+ });
57
+ }
58
+ const contentBuffer = fs.readFileSync(cacheDir + filename);
59
+ res.setHeader('Content-Type', 'text/javascript');
60
+ res.end(contentBuffer);
61
+ });
62
+ }
63
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@ws-ui/vite-plugins",
3
+ "private": false,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^20.14.9",
17
+ "typescript": "^5.2.2",
18
+ "vite": "^4.5.3"
19
+ },
20
+ "dependencies": {
21
+ "import-meta-resolve": "^4.0.0"
22
+ }
23
+ }