@md-plugins/vite-examples-plugin 0.1.0-alpha.1

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024-present, Jeff Galbraith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # @md-plugins/vite-examples-plugin
2
+
3
+ A Vite plugin that facilitates handling Vue example files in both development and production modes. The plugin allows you to load and transform example components and their raw source code for usage in your application.
4
+
5
+ ## Features
6
+
7
+ - Supports loading Vue example files dynamically during development.
8
+ - Generates import and export statements for Vue example files in production.
9
+ - Easily handles raw and compiled component imports.
10
+ - Enables seamless integration of example files into your project.
11
+
12
+ ## Installation
13
+
14
+ Install the plugin via your preferred package manager:
15
+
16
+ ```bash
17
+ # npm
18
+ npm install @md-plugins/vite-examples-plugin
19
+
20
+ # yarn
21
+ yarn add @md-plugins/vite-examples-plugin
22
+
23
+ # pnpm
24
+ pnpm add @md-plugins/vite-examples-plugin
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Basic Setup with Vite
30
+
31
+ To use the `viteExamplesPlugin`, configure it in your Vite project:
32
+
33
+ ```js
34
+ import { defineConfig } from 'vite';
35
+ import vue from '@vitejs/plugin-vue';
36
+ import { viteExamplesPlugin } from '@md-plugin/vite-examples-plugin';
37
+
38
+ export default defineConfig({
39
+ plugins: [vue(), viteExamplesPlugin('/absolute/path/to/examples')],
40
+ });
41
+ ```
42
+
43
+ ### Manual Chunk Splitting with Vite
44
+
45
+ ```js
46
+ import { defineConfig } from 'vite';
47
+ import vue from '@vitejs/plugin-vue';
48
+ import { viteExamplesPlugin, viteManualChunks } from 'vite-examples-plugin';
49
+
50
+ export default defineConfig({
51
+ plugins: [vue(), viteExamplesPlugin('/absolute/path/to/examples')],
52
+ build: {
53
+ chunkSizeWarningLimit: 650,
54
+ rollupOptions: {
55
+ output: {
56
+ manualChunks: viteManualChunks,
57
+ },
58
+ },
59
+ },
60
+ });
61
+ ```
62
+
63
+ ## Quasar Framework Configuration
64
+
65
+ 1. Update `quasar.config.(js|ts)`:
66
+
67
+ ```js
68
+ import { viteExamplesPlugin } from '@md-plugin/vite-examples-plugin';
69
+
70
+ export default defineConfig((ctx) => {
71
+ // ...
72
+ ```
73
+
74
+ ```js
75
+ build: {
76
+ vitePlugins: [
77
+ viteExamplesPlugin(ctx.appPaths.srcDir + '/examples'),
78
+ // ...
79
+ ],
80
+ },
81
+ }
82
+ ```
83
+
84
+ ### Manual Chunk Splitting with Quasar
85
+
86
+ ```js
87
+ import {
88
+ viteExamplesPlugin,
89
+ viteManualChunks,
90
+ } from '@md-plugins/vite-examples-plugin';
91
+ ```
92
+
93
+ ```js
94
+ build: {
95
+ extendViteConf(viteConf, { isClient }) {
96
+ if (ctx.prod && isClient) {
97
+ if (!viteConf.build) {
98
+ viteConf.build = {}
99
+ }
100
+ viteConf.build.chunkSizeWarningLimit = 650
101
+ viteConf.build.rollupOptions = {
102
+ output: { manualChunks: viteManualChunks },
103
+ }
104
+ }
105
+ },
106
+ }
107
+ ```
108
+
109
+ ## How viteManualChunks Works
110
+
111
+ The `viteManualChunks` function analyzes the module ID and assigns it to a specific chunk:
112
+
113
+ 1. **`Vendor Chunk`**: Files from `node_modules` matching libraries like `vue`, `@vue`, `quasar`, and `vue-router` are assigned to the `vendor` chunk.
114
+
115
+ 2. **`Examples Chunk`**: Example files matching the pattern `examples:<name>` or located in `src/examples/<name>` are grouped into chunks named `e.<name>`.
116
+
117
+ ### Example
118
+
119
+ Given the following files:
120
+
121
+ ```bash
122
+ node_modules/vue/index.js
123
+ src/examples/example1/Example1.vue
124
+ src/examples/example2/Example2.vue
125
+ ```
126
+
127
+ The resulting chunks might look like:
128
+
129
+ ```bash
130
+ vendor.js // Contains Vue, Quasar, Vue Router, etc.
131
+ e.example1.js // Contains Example1.vue
132
+ e.example2.js // Contains Example2.vue
133
+ ```
134
+
135
+ This helps facilitate loading and chunking in your application for your examples.
136
+
137
+ ## Example Folder Structure
138
+
139
+ ```bash
140
+ src/
141
+ examples/
142
+ example1/
143
+ Example1.vue
144
+ example2/
145
+ Example2.vue
146
+ ```
147
+
148
+ ## How It Works
149
+
150
+ The plugin provides two modes of operation based on the environment:
151
+
152
+ ### Development Mode
153
+
154
+ During development, the plugin uses Vite's `import.meta.glob` to dynamically load Vue example components and their raw source code:
155
+
156
+ ```ts
157
+ export const code = import.meta.glob('/src/examples/example1/*.vue', {
158
+ eager: true,
159
+ });
160
+ export const source = import.meta.glob('/src/examples/example1/*.vue', {
161
+ query: '?raw',
162
+ import: 'default',
163
+ eager: true,
164
+ });
165
+ ```
166
+
167
+ ### Production Mode
168
+
169
+ In production, the plugin preloads example components and their raw source code, generating import and export statements:
170
+
171
+ ```ts
172
+ import Example1 from 'app/src/examples/example1/Example1.vue';
173
+ import RawExample1 from 'app/src/examples/example1/Example1.vue?raw';
174
+
175
+ export { Example1, RawExample1 };
176
+ ```
177
+
178
+ ## Development Notes
179
+
180
+ The plugin is structured with the following components:
181
+
182
+ 1. `devLoad` Function
183
+ Generates dynamic imports for example files during development.
184
+
185
+ 2. `prodLoad` Function
186
+ Creates preloaded import and export statements for example files in production.
187
+
188
+ 3. `vitePlugin` Function
189
+ Constructs the Vite plugin with resolveId and load methods.
190
+
191
+ 4. `viteExamplesPlugin` Function
192
+ Sets the target folder and initializes the plugin.
193
+
194
+ ## Error Handling
195
+
196
+ If the `targetFolder` is not defined when the plugin is initialized, an error will be thrown:
197
+
198
+ ```ts
199
+ throw new Error('targetFolder is not defined');
200
+ ```
201
+
202
+ ## License
203
+
204
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Creates a Vite plugin for handling Markdown examples.
3
+ *
4
+ * This function sets up the target folder for example files and returns a function
5
+ * that creates the actual Vite plugin. The returned plugin resolves and loads
6
+ * example code based on the production or development environment.
7
+ *
8
+ * @param path - The path to the directory containing the example files.
9
+ * This path will be used as the target folder for resolving examples.
10
+ *
11
+ * @returns A function that creates a Vite plugin. This function takes a boolean
12
+ * parameter indicating whether the build is in production mode and
13
+ * returns the configured Vite plugin object.
14
+ */
15
+ declare function viteExamplesPlugin(path: string): (isProd: boolean) => {
16
+ name: string;
17
+ enforce: 'pre';
18
+ resolveId(id: string): string | undefined;
19
+ load(id: string): string | undefined;
20
+ };
21
+
22
+ /**
23
+ * A function to determine the manual chunk name for a given module ID.
24
+ *
25
+ * @param id - The module ID to analyze.
26
+ * @returns A string representing the chunk name or `undefined`.
27
+ */
28
+ declare function viteManualChunks(id: string): string | undefined;
29
+
30
+ export { viteExamplesPlugin, viteManualChunks };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Creates a Vite plugin for handling Markdown examples.
3
+ *
4
+ * This function sets up the target folder for example files and returns a function
5
+ * that creates the actual Vite plugin. The returned plugin resolves and loads
6
+ * example code based on the production or development environment.
7
+ *
8
+ * @param path - The path to the directory containing the example files.
9
+ * This path will be used as the target folder for resolving examples.
10
+ *
11
+ * @returns A function that creates a Vite plugin. This function takes a boolean
12
+ * parameter indicating whether the build is in production mode and
13
+ * returns the configured Vite plugin object.
14
+ */
15
+ declare function viteExamplesPlugin(path: string): (isProd: boolean) => {
16
+ name: string;
17
+ enforce: 'pre';
18
+ resolveId(id: string): string | undefined;
19
+ load(id: string): string | undefined;
20
+ };
21
+
22
+ /**
23
+ * A function to determine the manual chunk name for a given module ID.
24
+ *
25
+ * @param id - The module ID to analyze.
26
+ * @returns A string representing the chunk name or `undefined`.
27
+ */
28
+ declare function viteManualChunks(id: string): string | undefined;
29
+
30
+ export { viteExamplesPlugin, viteManualChunks };
package/dist/index.mjs ADDED
@@ -0,0 +1,68 @@
1
+ import { join } from 'node:path';
2
+ import { globSync } from 'tinyglobby';
3
+
4
+ const moduleIdRE = /^examples:/;
5
+ const resolvedIdPrefix = "\0examples:";
6
+ let targetFolder = "";
7
+ function devLoad(id) {
8
+ if (id.startsWith(resolvedIdPrefix)) {
9
+ const query = `'/src/examples/${id.substring(id.indexOf(":") + 1)}/*.vue'`;
10
+ return `export const code = import.meta.glob(${query}, { eager: true })
11
+ export const source = import.meta.glob(${query}, { query: '?raw', import: 'default', eager: true })`;
12
+ }
13
+ return void 0;
14
+ }
15
+ function prodLoad(id) {
16
+ if (id.startsWith(resolvedIdPrefix)) {
17
+ const exampleId = id.substring(id.indexOf(":") + 1);
18
+ const files = globSync("*.vue", { cwd: join(targetFolder, exampleId) });
19
+ const importList = files.map(
20
+ (entry) => entry.substring(0, entry.length - 4)
21
+ );
22
+ const importStatements = importList.map(
23
+ (entry) => `import ${entry} from 'app/src/examples/${exampleId}/${entry}.vue'
24
+ import Raw${entry} from 'app/src/examples/${exampleId}/${entry}.vue?raw'`
25
+ ).join("\n");
26
+ const exportStatements = importList.map((entry) => `${entry},Raw${entry}`).join(",");
27
+ return importStatements + `
28
+ export {${exportStatements}}`;
29
+ }
30
+ return void 0;
31
+ }
32
+ function vitePlugin(isProd) {
33
+ if (!targetFolder) {
34
+ throw new Error("targetFolder is not defined");
35
+ }
36
+ return {
37
+ name: "markdown-examples",
38
+ enforce: "pre",
39
+ // before vue
40
+ resolveId(id) {
41
+ if (moduleIdRE.test(id)) {
42
+ return "\0" + id;
43
+ }
44
+ return void 0;
45
+ },
46
+ load: isProd ? prodLoad : devLoad
47
+ };
48
+ }
49
+ function viteExamplesPlugin(path) {
50
+ targetFolder = path;
51
+ return vitePlugin;
52
+ }
53
+
54
+ const vendorRE = /node_modules[\\/](vue|@vue|quasar|vue-router)[\\/](.*)\.(m?js|css|sass)$/;
55
+ const exampleRE = /examples:([a-zA-Z0-9]+)$|src[\\/]examples[\\/]([a-zA-Z0-9-]+)/;
56
+ function viteManualChunks(id) {
57
+ if (vendorRE.test(id)) {
58
+ return "vendor";
59
+ }
60
+ const examplesMatch = exampleRE.exec(id);
61
+ if (examplesMatch !== null) {
62
+ const name = examplesMatch[1] || examplesMatch[2];
63
+ return `e.${name}`;
64
+ }
65
+ return void 0;
66
+ }
67
+
68
+ export { viteExamplesPlugin, viteManualChunks };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@md-plugins/vite-examples-plugin",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "A Vite plugin for @md-plugins for handling imported examples in markdown files.",
5
+ "keywords": [
6
+ "markdown-it",
7
+ "quasarframework",
8
+ "vue",
9
+ "utils",
10
+ "vite",
11
+ "vite-plugin"
12
+ ],
13
+ "homepage": "https://github.com/md-plugins",
14
+ "bugs": {
15
+ "url": "https://github.com/md-plugins/md-plugins/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/md-plugins/md-plugins.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": "hawkeye64 <galbraith64@gmail.com>",
23
+ "type": "module",
24
+ "exports": {
25
+ ".": {
26
+ "import": {
27
+ "types": "./dist/index.d.mts",
28
+ "default": "./dist/index.mjs"
29
+ }
30
+ }
31
+ },
32
+ "module": "./dist/index.mjs",
33
+ "types": "./dist/index.d.ts",
34
+ "files": [
35
+ "./dist"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "dependencies": {
41
+ "tinyglobby": "^0.2.10"
42
+ },
43
+ "scripts": {
44
+ "build": "unbuild",
45
+ "clean": "rm -rf dist"
46
+ }
47
+ }