@svelte-put/preprocess-inline-svg
Version:
minimal svg inliner from local resources at build time
204 lines (199 loc) • 6.92 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
// src/preprocessor/preprocessor.internals.ts
import fs from "fs";
import path from "path";
// ../preprocess-helpers/src/index.js
function getAttribute(source, node, attributeName) {
const attr = node.attributes.find(
(attr2) => attr2.name === attributeName && attr2.type === "Attribute"
);
if (attr) {
let raw = source.slice(attr.start + attributeName.length + 1, attr.end);
if (raw.startsWith('"') && raw.endsWith('"')) {
raw = raw.slice(1, -1);
}
return raw;
}
}
// src/preprocessor/preprocessor.internals.ts
import { toHtml } from "hast-util-to-html";
import MagicString from "magic-string";
import { walk } from "svelte/compiler";
import { parse } from "svelte-parse-markup";
import { parse as parseSvg } from "svg-parser";
var DEFAULT_SOURCES_CONFIG = {
directories: [],
attributes: {}
};
function resolveSourceOptions(options) {
return {
directories: (options == null ? void 0 : options.directories) ? Array.isArray(options.directories) ? options.directories : [options.directories] : DEFAULT_SOURCES_CONFIG.directories,
attributes: (options == null ? void 0 : options.attributes) ? __spreadValues(__spreadValues({}, DEFAULT_SOURCES_CONFIG.attributes), options.attributes) : DEFAULT_SOURCES_CONFIG.attributes
};
}
function resolveSources(sources) {
if (!sources)
return { local: DEFAULT_SOURCES_CONFIG, dirs: [] };
if (!Array.isArray(sources)) {
if (!sources.directories) {
return {
local: resolveSourceOptions(sources),
dirs: []
};
}
const dir = resolveSourceOptions(sources);
const local = __spreadProps(__spreadValues({}, dir), {
directories: []
});
return { local, dirs: [dir] };
}
const inputsWithoutDirectories = sources.filter((i) => !i.directories);
if (inputsWithoutDirectories.length > 1) {
throw new Error(
"\n@svelte-put/preprocess-inline-svg: only one default input (one without `directories` option) is allowed"
);
}
return {
local: resolveSourceOptions(inputsWithoutDirectories[0]),
dirs: sources.filter((i) => !!i.directories).map(resolveSourceOptions)
};
}
var DEFAULT_INLINE_SVG_CONFIG = {
inlineSrcAttributeName: "data-inline-src",
keepInlineSrcAttribute: false
};
function resolveInlineSvgConfig(config = {}) {
var _a, _b;
return {
inlineSrcAttributeName: (_a = config.inlineSrcAttributeName) != null ? _a : DEFAULT_INLINE_SVG_CONFIG.inlineSrcAttributeName,
keepInlineSrcAttribute: (_b = config.keepInlineSrcAttribute) != null ? _b : DEFAULT_INLINE_SVG_CONFIG.keepInlineSrcAttribute
};
}
function findSvgSrc(filename, directories, inlineSrc) {
let resolvedSrc = void 0;
if (inlineSrc) {
if (!inlineSrc.endsWith(".svg"))
inlineSrc += ".svg";
if (directories.length === 0) {
resolvedSrc = path.join(path.dirname(filename), inlineSrc);
if (!fs.existsSync(resolvedSrc))
resolvedSrc = void 0;
} else {
for (const dir of directories) {
resolvedSrc = path.join(dir, inlineSrc);
if (!path.isAbsolute(resolvedSrc)) {
resolvedSrc = path.join(process.cwd(), resolvedSrc);
}
if (fs.existsSync(resolvedSrc))
break;
else
resolvedSrc = void 0;
}
}
}
return resolvedSrc;
}
function transform(code, filename, sources, config) {
const { local, dirs } = sources;
const { inlineSrcAttributeName, keepInlineSrcAttribute } = config;
const s = new MagicString(code);
const ast = parse(code, { filename });
walk(ast.html, {
enter(_node) {
const node = _node;
if (node.type !== "Element" || node.name !== "svg")
return;
let options = local;
let inlineSrc = getAttribute(code, node, inlineSrcAttributeName);
let svgSource = findSvgSrc(filename, options.directories, inlineSrc);
if (!svgSource) {
for (let i = 0; i < dirs.length; i++) {
options = dirs[i];
inlineSrc = getAttribute(code, node, inlineSrcAttributeName);
svgSource = findSvgSrc(filename, options.directories, inlineSrc);
if (svgSource)
break;
}
}
if (!inlineSrc)
return;
if (!svgSource) {
throw new Error(
`
@svelte-put/preprocess-inline-svg: cannot find svg source for ${inlineSrc} at ${filename}`
);
}
const svgStr = fs.readFileSync(svgSource, "utf8").replace(/&/g, "&");
const hast = parseSvg(svgStr);
const svg = hast.children[0];
const attributes = __spreadValues(__spreadValues({}, svg.properties), options.attributes);
node.attributes.map((attr) => {
if (attr.type === "Attribute") {
if (attr.name === inlineSrcAttributeName && !keepInlineSrcAttribute) {
s.remove(attr.start, attr.end);
}
if (attributes[attr.name] && attr.value.length === 1) {
delete attributes[attr.name];
}
}
});
for (const [name, value] of Object.entries(attributes)) {
s.appendRight(node.start + "<svg".length, ` ${name}="${value}" `);
}
let insertIndex = node.end - "/>".length;
if (s.slice(insertIndex, node.end) !== "/>") {
insertIndex = node.end - "</svg>".length;
}
const content = toHtml(svg.children, {
allowDangerousCharacters: true
});
s.update(insertIndex, node.end, `>${content}</svg>`);
}
});
return {
code: s.toString(),
map: s.generateMap()
};
}
// src/preprocessor/preprocessor.ts
function inlineSvg(sources, config) {
const rSources = resolveSources(sources);
const rConfig = resolveInlineSvgConfig(config);
return {
markup({ content, filename }) {
return transform(content, filename, rSources, rConfig);
}
};
}
// src/index.ts
var src_default = inlineSvg;
export {
DEFAULT_INLINE_SVG_CONFIG,
DEFAULT_SOURCES_CONFIG,
src_default as default,
findSvgSrc,
inlineSvg,
resolveInlineSvgConfig,
resolveSourceOptions,
resolveSources,
transform
};
//# sourceMappingURL=index.js.map