@kanton-basel-stadt/designsystem
Version:
Unplugin to install the digital design system of the canton of Basel-Stadt
311 lines (294 loc) • 9.81 kB
JavaScript
import {
postcss_config_default
} from "./chunk-MSCKX2TC.js";
// src/index.ts
import { createUnplugin } from "unplugin";
// src/core/unplugins/postcssTailwind.ts
import fs from "node:fs";
import path4 from "node:path";
// src/core/utils/getConfigsPath.ts
import path2 from "node:path";
// src/core/utils/getDirName.ts
import path from "node:path";
import { fileURLToPath } from "node:url";
function getDirName() {
return path.dirname(fileURLToPath(import.meta.url));
}
// src/core/utils/getConfigsPath.ts
function getConfigsPath() {
const dirname = getDirName();
return path2.resolve(`${dirname}/configs/`);
}
// src/core/utils/getPostcssConfig.ts
import merge from "lodash.merge";
import loadOptions from "postcss-load-config/src/options.js";
import loadPlugins from "postcss-load-config/src/plugins.js";
async function getPostcssConfig(configPath, tailwindConfig) {
if (tailwindConfig) {
postcss_config_default.plugins.tailwindcss.config = merge(postcss_config_default.plugins.tailwindcss.config, tailwindConfig);
}
const file = `${configPath}/postcss.config.ts`;
return {
file,
options: await loadOptions(postcss_config_default, file),
plugins: await loadPlugins(postcss_config_default, file)
};
}
// src/core/utils/transformIdsInCode.ts
import path3 from "node:path";
import MagicString from "magic-string";
function transformIdsInCode(code, id) {
let dirname = getDirName();
if (dirname.endsWith(path3.sep)) {
dirname = dirname.replace(/[\\/]+$/, "");
}
if (dirname.endsWith("dist")) {
dirname = dirname.replace(/[\\/]+dist$/, "");
}
const s = new MagicString(code);
s.replace(/(['"(]+)(@{1,2})kanton-basel-stadt\/designsystem\/(icons\/symbols\/(\w+)|([^"')]+))(['")]+)/g, (_, surroundingStart, ats, fullPathMatch, _2, iconMatch, surroundingEnd) => {
if (ats.length === 2) {
return `${surroundingStart}@kanton-basel-stadt/designsystem/${fullPathMatch}${surroundingEnd}`;
}
if (fullPathMatch.startsWith(path3.sep) || fullPathMatch.startsWith("/")) {
fullPathMatch = fullPathMatch.replace(/^[\\/]+/, "");
}
if (fullPathMatch.startsWith("icons/symbol/")) {
return `${surroundingStart}~${iconMatch}${surroundingEnd}`;
}
if (fullPathMatch.startsWith("dist")) {
fullPathMatch = fullPathMatch.replace(/^dist[\\/]+/, "");
}
fullPathMatch = fullPathMatch.replace(/\//g, path3.sep);
return `${surroundingStart}${dirname}${path3.sep}dist${path3.sep}${fullPathMatch}${surroundingEnd}`;
});
if (!s.hasChanged()) {
return;
}
return {
code: s.toString(),
map: s.generateMap({ source: id, includeContent: true, hires: true })
};
}
// src/core/unplugins/postcssTailwind.ts
function getPostcssTailwindUnplugin(options) {
const postcssConfig = getPostcssConfig(getConfigsPath(), options.tailwindOptions?.config);
return {
name: "@kanton-basel-stadt/designsystem/postcss-tailwind",
esbuild: {
async setup(build) {
build.onLoad({ filter: /\.woff2?$/i }, () => {
return { loader: "copy" };
});
const postcss = (await import("postcss")).default;
const loadedPostcss = await postcssConfig;
const postcssInstance = postcss(loadedPostcss.plugins);
build.onLoad({ filter: /\.css$/i }, async (args) => {
const code = fs.readFileSync(args.path, "utf-8");
const transformed = transformIdsInCode(code, args.path);
const processed = await postcssInstance.process(transformed ? transformed.code : code, {
from: args.path,
to: options.tailwindOptions?.targetDir || "dist",
map: {
absolute: true,
from: args.path
}
});
return { contents: processed.content, loader: "css" };
});
}
},
webpack(compiler) {
compiler.hooks.beforeRun.tapPromise("@kanton-basel-stadt/designsystem", async (params) => {
let initialLoader = "style-loader";
if (params.options.mode === "production") {
const MiniCssExtractPlugin = (await import("mini-css-extract-plugin")).default;
new MiniCssExtractPlugin({
filename: "app.css"
}).apply(params);
initialLoader = {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
// adjust based on where fonts are output relative to your CSS
}
};
}
const postcssConfigLoaded = await postcssConfig;
const cssLoaders = [
initialLoader,
{
loader: "css-loader",
options: {
url: true,
modules: false,
importLoaders: 1
}
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: postcssConfigLoaded.plugins,
to: options.tailwindOptions?.targetDir || "dist",
modules: false
}
}
}
];
params.options.module.rules.push({
test: /\.css$/,
use: cssLoaders
});
params.options.module.rules.unshift({
test: /\.(woff2?)$/i,
type: "asset/resource"
});
});
},
rollup: {
async options(rollupOptions) {
const postcss = (await import("rollup-plugin-postcss")).default;
const urlCopy = (await import("postcss-url-copy")).default;
if (!rollupOptions.plugins) {
rollupOptions.plugins = [];
}
const fullTargetDir = path4.resolve(options.tailwindOptions?.targetDir || "dist");
const plugins = [
...(await postcssConfig).plugins,
urlCopy({
destPath: fullTargetDir,
assetsDestPath: `${fullTargetDir}${path4.sep}assets`,
transformUrlBeforeLoad(url) {
return url.replace(/@kanton-basel-stadt\/designsystem\//g, `.${path4.sep}node_modules${path4.sep}@kanton-basel-stadt${path4.sep}designsystem${path4.sep}dist${path4.sep}`);
},
transformUrlBeforeWrite(url) {
return url.replace(fullTargetDir, ".");
}
})
];
if (Array.isArray(rollupOptions.plugins)) {
rollupOptions.plugins.unshift(postcss({
extract: true,
modules: false,
to: options.tailwindOptions?.targetDir || "dist/",
plugins
}));
}
return rollupOptions;
}
},
vite: {
async config() {
return {
css: {
postcss: await postcssConfig
}
};
}
}
};
}
// src/core/unplugins/transformIds.ts
function getTransformIdsUnplugin() {
return {
name: "@kanton-basel-stadt/designsystem/transform-ids",
enforce: "pre",
transform: transformIdsInCode,
transformInclude(id) {
return !id.endsWith(".woff") && !id.endsWith(".woff2");
},
esbuild: {
onLoadFilter: /\.(?!woff2?$)[^.]+$/i
},
vite: {
config() {
return {
optimizeDeps: {
exclude: ["@kanton-basel-stadt/designsystem/dist/configs/icons-index"]
}
};
}
}
};
}
// src/core/unplugins/unpluginIconsPatched.ts
import merge2 from "lodash.merge";
import { optimize } from "svgo";
import unpluginIcons from "unplugin-icons";
import { FileSystemIconLoader } from "unplugin-icons/loaders";
// src/core/utils/getAssetsPath.ts
import path5 from "node:path";
function getAssetsPath() {
const dirname = getDirName();
return path5.resolve(`${dirname}${path5.sep}assets${path5.sep}`);
}
// src/core/utils/consts.ts
var ICON_PATH_ALIAS = "@kanton-basel-stadt/designsystem/icons/symbol";
var ICON_PATH = "~icons/symbol";
// src/core/utils/transformIconId.ts
function transformIconId(id) {
return id.replace(ICON_PATH_ALIAS, ICON_PATH);
}
// src/core/unplugins/unpluginIconsPatched.ts
function getUnpluginIconsPatchedUnplugin(options, meta) {
const unpluginIconsConfig = {
customCollections: {
symbol: FileSystemIconLoader(`${getAssetsPath()}/symbols`, (svg) => {
const res = optimize(svg, {
plugins: [
"removeEmptyAttrs",
"removeDimensions",
// Width and height can mess with the rendering in some browsers.
"removeComments"
// Not needed for the final icon.
]
});
return res.data;
})
},
compiler: "web-components",
webComponents: {
autoDefine: true
}
};
const mergedUnpluginIconsConfig = merge2(unpluginIconsConfig, options.iconOptions);
if (mergedUnpluginIconsConfig.compiler !== "web-components") {
delete mergedUnpluginIconsConfig.webComponents;
}
let builtUnpluginIcons = unpluginIcons;
if ("default" in unpluginIcons)
builtUnpluginIcons = unpluginIcons.default;
const usableUnpluginIcons = builtUnpluginIcons.raw(mergedUnpluginIconsConfig, meta);
return {
...usableUnpluginIcons,
name: "unplugin-icons-patched",
resolveId(id) {
return usableUnpluginIcons.resolveId(transformIconId(id));
},
loadInclude(id) {
return usableUnpluginIcons.loadInclude(transformIconId(id));
},
async load(id) {
return await usableUnpluginIcons.load(transformIconId(id));
}
};
}
// src/index.ts
var unpluginFactory = (options, meta) => {
if (options === void 0) {
options = {};
}
return [
getTransformIdsUnplugin(),
getUnpluginIconsPatchedUnplugin(options, meta),
getPostcssTailwindUnplugin(options)
];
};
var unplugin = /* @__PURE__ */ createUnplugin(unpluginFactory);
var src_default = unplugin;
export {
unpluginFactory,
unplugin,
src_default
};