elearning/Frontend-Learner/node_modules/nuxt-quasar-ui/dist/module.mjs
2026-01-13 10:48:02 +07:00

584 lines
19 KiB
JavaScript

import path, { dirname, resolve } from 'node:path';
import { useNuxt, logger, defineNuxtModule, createResolver, resolvePath, addPlugin, addTemplate, addTypeTemplate, addComponent, addImports, addImportsSources } from '@nuxt/kit';
import { parseNodeModulePath } from 'mlly';
import MagicString from 'magic-string';
import os from 'node:os';
import { readFile } from 'node:fs/promises';
import pMemoize from 'p-memoize';
import semver from 'semver';
const version = "3.0.0";
const directivesRegExp = /(?<=[ (])_?resolveDirective\(\s*["']([^'"]*)["'][^)]*\)/g;
function transformDirectivesPlugin(context) {
const { sourcemap } = useNuxt().options;
return {
name: "quasar:directive",
enforce: "post",
transform(code, id) {
const [filename] = id.split("?", 2);
if (!filename || !filename.endsWith(".vue"))
return null;
const s = new MagicString(code);
const directives = [];
let counter = 0;
s.replace(directivesRegExp, (full, name) => {
const directive = context.imports.directives.find((d) => d.kebabCase === name);
if (directive) {
const alias = `__q_directive_${counter++}`;
directives.push({
name: directive.name,
alias
});
return alias;
} else {
return full;
}
});
if (directives.length) {
s.prepend(
`${directives.map((d) => `import { ${d.name} as ${d.alias} } from "quasar"`).join("\n")}
`
);
}
if (s.hasChanged()) {
return {
code: s.toString(),
map: sourcemap[context.mode] ? s.generateMap({ source: id, includeContent: true }) : void 0
};
}
}
};
}
const isWindows = os.platform() === "win32";
function slash(p) {
return p.replace(/\\/g, "/");
}
function normalizePath(id) {
return path.posix.normalize(isWindows ? slash(id) : id);
}
const readFileMemoized = pMemoize(async (path2) => {
return readFile(path2, "utf-8");
});
const readJSON = pMemoize(async (path2) => {
return JSON.parse(await readFile(path2, "utf-8"));
});
const PASCAL_CASE = /[a-z][A-Z]|^[A-Z]/g;
function kebabCase(string) {
return string.replaceAll(
PASCAL_CASE,
(match) => match.length === 1 ? match[0].toLowerCase() : `${match[0]}-${match[1].toLowerCase()}`
);
}
function hasKeys(object) {
return Object.keys(object || {}).length > 0;
}
function parseVueRequest(id) {
const [filename = "", rawQuery] = id.split("?", 2);
const query = Object.fromEntries(new URLSearchParams(rawQuery));
if (query.vue != null) {
query.vue = true;
}
return {
filename,
query
};
}
function uniq(arr) {
return [...new Set(arr)];
}
function transformScssPlugin({ options }) {
const sassVariables = typeof options.sassVariables === "string" ? normalizePath(options.sassVariables) : options.sassVariables;
const scssTransform = createScssTransform("scss", sassVariables);
const sassTransform = createScssTransform("sass", sassVariables);
return {
name: "quasar:scss",
enforce: "pre",
transform(src, id) {
const { filename, query } = parseVueRequest(id);
let code;
if (query.vue && query.type === "style") {
const lang = Object.keys(query).find((k) => k.startsWith("lang."));
if (lang?.endsWith(".scss")) {
code = scssTransform(src);
} else if (lang?.endsWith(".sass")) {
code = sassTransform(src);
}
}
if (!query.vue) {
if (filename.endsWith(".scss")) {
code = scssTransform(src);
} else if (filename.endsWith(".sass")) {
code = sassTransform(src);
}
}
if (code) {
return { code, map: null };
}
}
};
}
function createScssTransform(fileExtension, sassVariables) {
return (content) => {
const hasQuasarVariables = content.includes("quasar/src/css/variables") || content.includes("quasar/dist/") || /@use\s+['"]quasar(?:[/'"]|$)/.test(content);
const sassUseStatements = [];
if (hasQuasarVariables) {
return content;
} else if (typeof sassVariables === "string") {
sassUseStatements.push(`@use '${sassVariables}' as *`);
} else {
sassUseStatements.push("@use 'quasar/src/css/variables.sass' as *");
}
sassUseStatements.push("");
const prefix = fileExtension === "sass" ? sassUseStatements.join("\n") : sassUseStatements.join(";\n");
const useIndex = Math.max(content.lastIndexOf("@use "), content.lastIndexOf("@forward "));
if (useIndex === -1) {
return prefix + content;
}
const newLineIndex = content.indexOf("\n", useIndex);
if (newLineIndex !== -1) {
const index = newLineIndex + 1;
return content.substring(0, index) + prefix + content.substring(index);
}
return `${content}
${prefix}`;
};
}
const QUASAR_ENTRY = "quasar";
const QUASAR_VIRTUAL_ENTRY = "/__quasar/entry.mjs";
function virtualQuasarEntryPlugin(context) {
const { resolveQuasar, quasarVersion } = context;
const quasarGte216 = semver.gte(quasarVersion, "2.16.0");
const clientEntry = quasarGte216 ? resolveQuasar("dist/quasar.client.js") : resolveQuasar("dist/quasar.esm.js");
const serverEntry = quasarGte216 ? resolveQuasar("dist/quasar.server.prod.js") : resolveQuasar("src/index.ssr.js");
return {
name: "quasar:entry",
enforce: "pre",
config(config) {
config.ssr ??= {};
config.ssr.noExternal ??= [];
if (config.ssr.noExternal !== true) {
config.ssr.noExternal = toArray(config.ssr.noExternal);
config.ssr.noExternal.push(/\/node_modules\/quasar\/src\//);
}
},
resolveId(id) {
if (id === QUASAR_ENTRY) {
return {
id: context.dev ? context.mode === "client" ? clientEntry : serverEntry : QUASAR_VIRTUAL_ENTRY,
moduleSideEffects: false
};
}
},
async load(id) {
if (!context.dev && id === QUASAR_VIRTUAL_ENTRY)
return Object.entries(context.imports.raw).filter(([, path]) => !path.includes("/__tests__/")).map(([name, path]) => `export { default as ${name} } from "quasar/${path}"`).join("\n");
}
};
}
function toArray(value) {
return Array.isArray(value) ? value : [value];
}
const moduleName = "nuxt-quasar-ui";
const quasarFontsPath = "quasar/fonts";
const quasarAnimationsPath = "quasar/animations";
const quasarIconsPath = "quasar/icons";
const quasarCssPath = "quasar/css";
const quasarBrandPath = "quasar/brand";
const RESOLVED_ID$1 = "/__quasar/animations.css";
const RESOLVED_ID_WITH_QUERY_RE$1 = /([/\\])__quasar\1animations\.css(\?.*)?$/;
function virtualAnimationsPlugin({ options, resolveQuasarExtras }) {
return {
name: "quasar:animations",
resolveId(id) {
if (id.match(RESOLVED_ID_WITH_QUERY_RE$1))
return id;
const [path] = id.split("?");
if (path === quasarAnimationsPath)
return RESOLVED_ID$1;
},
async load(id) {
if (!RESOLVED_ID_WITH_QUERY_RE$1.test(id))
return;
let animations = options.extras?.animations || [];
if (animations === "all") {
const { generalAnimations, inAnimations, outAnimations } = await import('@quasar/extras/animate/animate-list.mjs');
animations = [...generalAnimations, ...inAnimations, ...outAnimations];
} else {
animations = uniq(animations);
}
const cssArray = await Promise.all(
animations.map(
(animation) => readFile(resolveQuasarExtras(`animate/${animation}.css`), "utf8")
)
);
return cssArray.join("\n");
}
};
}
const RESOLVED_ID = "/__quasar/brand.css";
const RESOLVED_ID_WITH_QUERY_RE = /([/\\])__quasar\1brand\.css(\?.*)?$/;
function virtualBrandPlugin(context) {
return {
name: "quasar:brand",
resolveId(id) {
if (id.match(RESOLVED_ID_WITH_QUERY_RE))
return id;
const [path] = id.split("?");
if (path === quasarBrandPath)
return RESOLVED_ID;
},
load(id) {
if (RESOLVED_ID_WITH_QUERY_RE.test(id))
return [
":root {",
...Object.entries(context.options.config?.brand || {}).map(([name, color]) => ` --q-${name}: ${color};`),
"}"
].join("\n");
}
};
}
function setupCss(css, options) {
const brand = options.config?.brand || {};
if (css.includes(quasarBrandPath)) {
logger.warn('Re-ordering "quasar/brand" is deprecated. In a future version, brand variables will always be defined in body tag.');
}
if (!css.includes(quasarBrandPath) && Object.keys(brand).length) {
css.unshift(quasarBrandPath);
}
const quasarCss = [
typeof options.sassVariables === "string" ? "quasar/dist/quasar.sass" : "quasar/dist/quasar.css"
];
if (options.cssAddon) {
quasarCss.push("quasar/dist/quasar.addon.css");
}
const index = css.indexOf(quasarCssPath);
if (index !== -1) {
css.splice(index, 1, ...quasarCss);
} else {
css.unshift(...quasarCss);
}
const animations = options.extras?.animations || [];
if (!css.includes(quasarAnimationsPath) && animations.length) {
css.unshift(quasarAnimationsPath);
}
if (options.extras?.fontIcons) {
const i = css.indexOf(quasarIconsPath);
if (i !== -1) {
css.splice(i, 1, ...uniq(options.extras.fontIcons).map(resolveFontIcon));
} else {
css.unshift(...uniq(options.extras.fontIcons).map(resolveFontIcon));
}
}
if (options.extras?.font) {
const i = css.indexOf(quasarFontsPath);
if (i !== -1) {
css.splice(i, 1, resolveFont(options.extras.font));
} else {
css.unshift(resolveFont(options.extras.font));
}
}
return css;
}
function resolveFontIcon(icon) {
return `@quasar/extras/${icon}/${icon}.css`;
}
function resolveFont(font) {
return `@quasar/extras/${font}/${font}.css`;
}
function when(condition, content) {
return condition ? typeof content === "function" ? content() : content : "";
}
function generateTemplateQuasarConfig(context) {
const plugins = uniq(context.options.plugins || []);
const { config, lang, iconSet, components } = context.options;
const componentsWithDefaults = Object.entries(components?.defaults || {}).filter(([_, props]) => hasKeys(props)).map(([name]) => name);
const ext = semver.gte(context.quasarVersion, "2.16.0") ? ".js" : ".mjs";
return `${when(lang, () => `import lang from "quasar/lang/${lang}${ext}"`)}
${when(typeof iconSet === "string", () => `import iconSet from "quasar/icon-set/${iconSet}${ext}"`)}
${when(plugins.length, () => `import { ${plugins} } from "quasar"`)}
${when(componentsWithDefaults.length, () => `import { ${componentsWithDefaults} } from "quasar"`)}
export const componentsWithDefaults = { ${componentsWithDefaults} }
export const appConfigKey = ${JSON.stringify(context.options.appConfigKey)}
export const quasarNuxtConfig = {
${when(lang, "lang,")}
${typeof iconSet === "string" ? "iconSet" : `iconSet: ${iconSet ? JSON.stringify(iconSet) : '"material-icons"'}`},
components: ${JSON.stringify(components || {})},
plugins: {${plugins.join(",") || ""}},
${when(config, () => `config: ${JSON.stringify(config)}`)}
}`;
}
async function generateTemplateShims(context) {
const componentNames = context.imports.components.map((c) => c.name);
return `type KeysMatching<T, V> = {
[K in keyof T]-?: T[K] extends V ? K : never
}[keyof T] & keyof T
type OptionalKeys<T extends object> = Exclude<{
[K in keyof T]: T extends Record<K, T[K]> ? never : K
}[keyof T], undefined>
type OmitMatching<T extends object, V> = Omit<T, KeysMatching<T, V>>
type OmitFnProps<T extends object> = OmitMatching<T, ((...args: any[]) => any) | undefined>
type PickOptionalProps<T extends object> = Pick<T, OptionalKeys<T>>
declare module '${moduleName}' {
interface QuasarComponentDefaults {
${componentNames.map(
(name) => ` ${name}?: PickOptionalProps<OmitFnProps<import("quasar").${name}Props>>`
).join("\n")}
}
}
declare module '@nuxt/schema' {
interface AppConfigInput {
[${JSON.stringify(context.options.appConfigKey)}]?: import("nuxt-quasar-ui").QuasarUIConfiguration
}
interface AppConfig {
[${JSON.stringify(context.options.appConfigKey)}]?: import("nuxt-quasar-ui").QuasarUIConfiguration
}
}
export {}
`;
}
const module$1 = defineNuxtModule({
meta: {
name: "quasar",
version,
configKey: "quasar",
compatibility: {
nuxt: ">=3.0.0"
}
},
defaults: {
lang: "en-US",
iconSet: "material-icons",
autoIncludeIconSet: true,
cssAddon: false,
sassVariables: false,
appConfigKey: "nuxtQuasar",
components: {
defaults: {},
autoImport: true
},
plugins: [],
extras: {}
},
async setup(options, nuxt) {
const { resolve: resolveLocal } = createResolver(import.meta.url);
const { resolve: resolveQuasar } = createResolver(dirname(await resolvePath("quasar/package.json")));
const { resolve: resolveQuasarExtras } = createResolver(dirname(await resolvePath("@quasar/extras/package.json")));
const { version: quasarVersion } = await readJSON(resolveQuasar("package.json"));
const importMap = await readJSON(resolveQuasar("dist/transforms/import-map.json"));
const transformAssetUrls = await readJSON(resolveQuasar("dist/transforms/loader-asset-urls.json"));
const imports = categorizeImports(importMap, resolveQuasar);
const sassVersion = await getSassVersion();
const baseContext = {
ssr: nuxt.options.ssr,
dev: nuxt.options.dev,
imports,
options,
quasarVersion,
sassVersion,
resolveLocal,
resolveQuasar,
resolveQuasarExtras
};
if (options.autoIncludeIconSet && typeof options.iconSet === "string" && isFontIconSet(options.iconSet) && !options.extras?.fontIcons?.includes(options.iconSet)) {
options.extras ??= {};
options.extras.fontIcons ??= [];
options.extras.fontIcons.push(options.iconSet);
}
setupCss(nuxt.options.css, options);
addPlugin(resolveLocal("./runtime/plugin"));
addTemplate({
write: true,
filename: "quasar.config.mjs",
getContents: () => generateTemplateQuasarConfig(baseContext)
});
addTypeTemplate({
filename: "quasar.shims.d.ts",
getContents: () => generateTemplateShims(baseContext)
});
if (options.components?.autoImport !== false) {
for (const component of imports.components) {
addComponent({
name: component.name,
export: component.name,
filePath: "quasar",
// TOFIX: Nuxt v3.13.2 tries to resolve full component paths with following PR: https://github.com/nuxt/nuxt/pull/28843
// Since this module has a custom way of resolving quasar, this breaks things.
// Adding this property prevents nuxt from resolving components, but since this is an internal property, it might break again in future.
// @ts-expect-error untyped internal property
_scanned: true
});
}
}
if (nuxt.options.imports.autoImport !== false) {
const ignoredComposables = ["useId", "useHydration"];
for (const composable of imports.composables.filter((c) => !ignoredComposables.includes(c.name))) {
addImports({
name: composable.name,
from: "quasar"
});
}
if (options.plugins) {
for (const plugin of uniq(options.plugins)) {
const pluginPath = imports.plugins.find((p) => p.name === plugin)?.path;
if (pluginPath) {
addImports({
name: plugin,
from: "quasar"
});
}
}
}
if (options.extras?.svgIcons) {
for (const iconSet of uniq(options.extras.svgIcons)) {
const icons = await getIconsFromIconset(iconSet, resolveQuasarExtras);
addImportsSources({
from: `@quasar/extras/${iconSet}`,
imports: icons
});
}
}
}
nuxt.hook("prepare:types", ({ references }) => {
references.unshift({ types: "quasar" });
});
nuxt.hook("vite:extendConfig", (config, { isClient, isServer }) => {
const ssr = nuxt.options.ssr;
const context = {
...baseContext,
mode: isServer ? "server" : "client"
};
config.optimizeDeps ??= {};
config.optimizeDeps.exclude ??= [];
config.optimizeDeps.exclude.push("quasar");
config.vue ??= {};
config.vue.template ??= {};
if (config.vue.template.transformAssetUrls !== false) {
config.vue.template.transformAssetUrls ??= {};
config.vue.template.transformAssetUrls = {
...config.vue.template.transformAssetUrls,
...transformAssetUrls
};
}
config.define = {
...config.define,
__QUASAR_VERSION__: `'${quasarVersion}'`,
__QUASAR_SSR__: ssr,
__QUASAR_SSR_SERVER__: ssr && isServer,
__QUASAR_SSR_CLIENT__: ssr && isClient,
__QUASAR_SSR_PWA__: false
};
config.plugins ??= [];
config.plugins.push(
virtualAnimationsPlugin(context),
virtualBrandPlugin(context),
transformDirectivesPlugin(context),
virtualQuasarEntryPlugin(context)
);
if (options.sassVariables) {
config.plugins.push(transformScssPlugin(context));
}
});
nuxt.hook("nitro:config", async (config) => {
config.replace = {
...config.replace,
__QUASAR_VERSION__: `'${quasarVersion}'`,
__QUASAR_SSR__: nuxt.options.ssr,
__QUASAR_SSR_SERVER__: true,
__QUASAR_SSR_CLIENT__: false,
__QUASAR_SSR_PWA__: false
};
config.externals ??= {};
config.externals.inline ??= [];
config.externals.inline.push("quasar");
});
nuxt.hook("devtools:customTabs", (tabs) => {
tabs.push({
name: "quasar",
title: "Quasar",
icon: "vscode-icons-file-type-light-quasar",
view: {
type: "iframe",
src: "https://quasar.dev/vue-components"
}
});
});
}
});
function isFontIconSet(iconSet) {
return !iconSet.startsWith("svg-");
}
function categorizeImports(importMap, quasarResolve) {
const imports = {
raw: importMap,
components: [],
composables: [],
directives: [],
plugins: []
};
for (const [name, path] of Object.entries(importMap)) {
const importData = {
name,
path: quasarResolve(path)
};
if (path.includes("/components/") && !path.includes("/__tests__/")) {
imports.components.push(importData);
} else if (path.includes("/composables/")) {
imports.composables.push(importData);
} else if (path.includes("/directives/")) {
imports.directives.push({
...importData,
kebabCase: kebabCase(name)
});
} else if (path.includes("/plugins/")) {
imports.plugins.push(importData);
}
}
return imports;
}
const iconDeclarationPattern = /^export declare const ([a-zA-Z\d]+): string;?$/gm;
async function getIconsFromIconset(iconSet, resolveQuasarExtras) {
try {
const icons = await readJSON(resolveQuasarExtras(`${iconSet}/icons.json`));
return icons;
} catch {
const path = resolveQuasarExtras(`${iconSet}/index.d.ts`);
const dts = await readFileMemoized(path);
const icons = [...dts.matchAll(iconDeclarationPattern)].map((arr) => arr[1]);
return icons;
}
}
async function getSassVersion() {
try {
const sassEntry = await resolvePath("sass");
const modulePath = parseNodeModulePath(sassEntry);
if (modulePath.dir) {
const { version: version2 } = await readJSON(resolve(modulePath.dir, modulePath.name, "./package.json"));
return version2;
}
} catch {
}
return null;
}
export { module$1 as default };