diff --git a/.gitignore b/.gitignore index 0d410d77..937ca066 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ wwwroot/ node_modules/ *.user .pnpm-debug.log +*.orig diff --git a/Lombiq.VueJs/Assets/Scripts/helpers/rollup-plugin-vue-sfc-orchard-core.js b/Lombiq.VueJs/Assets/Scripts/helpers/rollup-plugin-vue-sfc-orchard-core.js index da7fc11a..0f1eab04 100644 --- a/Lombiq.VueJs/Assets/Scripts/helpers/rollup-plugin-vue-sfc-orchard-core.js +++ b/Lombiq.VueJs/Assets/Scripts/helpers/rollup-plugin-vue-sfc-orchard-core.js @@ -109,11 +109,11 @@ module.exports = function vuePlugin() { const className = 'VueComponent-' + pascalCaseName; // Inject name and template properties. The "(? { const lowerCase = letter.toLowerCase(); return letter === lowerCase ? letter : '-' + lowerCase }) + .map((letter) => { + const lowerCase = letter.toLowerCase(); + return letter === lowerCase ? letter : '-' + lowerCase; + }) .join(''); } @@ -13,14 +16,21 @@ document.querySelectorAll('.lombiq-vue').forEach(async function initializeVueCom const { name, model } = JSON.parse(element.dataset.vue); const component = (await import(name + '.vue')).default; + const plugins = await Promise.all(element + .dataset + .plugins + .split(',') + .filter((word) => word?.trim()) + .map(async (word) => (await import(word.trim())).default)); + const hasEmit = Array.isArray(component?.emit); const vModel = Object .keys(model) - .map(property => ({ property: property, eventName: 'update:' + toKebabCase(property) })) - .filter(pair => !hasEmit || component.emit.includes(pair.eventName)) - .map(pair => ` @${pair.eventName}="viewModel.${pair.property} = $event"`); + .map((property) => ({ property: property, eventName: 'update:' + toKebabCase(property) })) + .filter((pair) => !hasEmit || component.emit.includes(pair.eventName)) + .map((pair) => ` @${pair.eventName}="viewModel.${pair.property} = $event"`); - createApp({ + const app = createApp({ data: function data() { return { viewModel: model, root: element }; }, @@ -30,5 +40,9 @@ document.querySelectorAll('.lombiq-vue').forEach(async function initializeVueCom window.VueApplications[element.id] = this; this.$appId = element.id; }, - }).mount(element); + }); + + plugins.forEach((plugin) => app.use(plugin)); + + app.mount(element); }); diff --git a/Lombiq.VueJs/ResourceManagementOptionsConfiguration.cs b/Lombiq.VueJs/ResourceManagementOptionsConfiguration.cs index c6ab00e6..abf5d2f2 100644 --- a/Lombiq.VueJs/ResourceManagementOptionsConfiguration.cs +++ b/Lombiq.VueJs/ResourceManagementOptionsConfiguration.cs @@ -12,7 +12,7 @@ public class ResourceManagementOptionsConfiguration : IConfigureOptions=4'} dev: true - /postcss@8.4.33: - resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} + /postcss@8.4.35: + resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 @@ -2649,19 +2649,19 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vue@3.4.19: - resolution: {integrity: sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==} + /vue@3.4.21: + resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@vue/compiler-dom': 3.4.19 - '@vue/compiler-sfc': 3.4.19 - '@vue/runtime-dom': 3.4.19 - '@vue/server-renderer': 3.4.19(vue@3.4.19) - '@vue/shared': 3.4.19 + '@vue/compiler-dom': 3.4.21 + '@vue/compiler-sfc': 3.4.21 + '@vue/runtime-dom': 3.4.21 + '@vue/server-renderer': 3.4.21(vue@3.4.21) + '@vue/shared': 3.4.21 dev: false /which-boxed-primitive@1.0.2: diff --git a/Readme.md b/Readme.md index 009ae334..484c5f3d 100644 --- a/Readme.md +++ b/Readme.md @@ -53,6 +53,33 @@ The packages will be automatically installed on build (i.e. `dotnet build`). You The build script can be configured by placing a JSON file (called _vue-sfc-compiler-pipeline.json_) in the project root. It can contain the same properties you can see in the `defaultOptions` variables in [vue-sfc-compiler-pipeline.js](Lombiq.VueJs/Assets/scripts/helpers/vue-sfc-compiler-pipeline.js). Any property set in the JSON file overrides the default value as the two objects are merged. +When configuring the `rollupNodeResolve` option (for [`@rollup/plugin-node-resolve`](https://www.npmjs.com/package/@rollup/plugin-node-resolve)), normally you could only pass in an array of exact matches due to the limitation of the JSON format. Instead, you can use `rollupNodeResolve.resolveOnlyRules` which is an object array in the following format: + +```json +{ + "rollupNodeResolve": { + "preferBuiltins": true, + "browser": true, + "mainFields": ["module", "jsnext:main"], + "resolveOnlyRules": [ + { + "regex": false, + "include": false, + "value": "vue" + }, + { + "regex": true, + " ": false, + "value": "^vuetify" + } + ] + }, + "isProduction": false +} +``` + +Here we excluded `vue` and packages starting with `vuetify` (e.g. `vuetify/components`) from the resolution, so they are treated as external. Then you can add `vuetify` using the resource manifest as a script module. + ## Using Vue.js Single File Components The module identifies Single File Components in the _Assets/Scripts/VueComponents_ directory and harvests them as shapes. They have a custom _.vue_ file renderer that displays the content of the `