convertigo-studio-web/src/convertigo.plugin.js
Rama develop · réplica de lectura del repositorio original.
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
const versions = {
'': { base: 3, md: 6 },
low: { base: 1.5, md: 3 },
none: { base: 0, md: 0 }
};
const props = {
gap: (v) => ({ gap: v }),
pl: (v) => ({ 'padding-left': v }),
pr: (v) => ({ 'padding-right': v }),
pt: (v) => ({ 'padding-top': v }),
pb: (v) => ({ 'padding-bottom': v }),
px: (v) => ({ 'padding-left': v, 'padding-right': v }),
py: (v) => ({ 'padding-top': v, 'padding-bottom': v }),
p: (v) => ({ 'padding-left': v, 'padding-right': v, 'padding-top': v, 'padding-bottom': v }),
ml: (v) => ({ 'margin-left': v }),
mr: (v) => ({ 'margin-right': v }),
mt: (v) => ({ 'margin-top': v }),
mb: (v) => ({ 'margin-bottom': v }),
mx: (v) => ({ 'margin-left': v, 'margin-right': v }),
my: (v) => ({ 'margin-top': v, 'margin-bottom': v }),
m: (v) => ({ 'margin-left': v, 'margin-right': v, 'margin-top': v, 'margin-bottom': v })
};
function getVersion(property, version, prefix = '', suffix = '') {
if (!versions[version]) {
return {};
}
return {
...props[property](`${prefix}--spacing(${versions[version].base})${suffix}`),
'@variant md': {
...props[property](`${prefix}--spacing(${versions[version].md})${suffix}`)
}
};
}
function dash(value) {
return value.length ? `-${value}` : '';
}
function merge(...sources) {
const output = {};
for (const source of sources) {
for (const key of Object.keys(source)) {
if (key in output && typeof output[key] == 'object' && typeof source[key] == 'object') {
output[key] = merge(output[key], source[key]);
} else {
output[key] = source[key];
}
}
}
for (const key of Object.keys(output).filter((k) => k.startsWith('@'))) {
const o = output[key];
delete output[key];
output[key] = o;
}
return output;
}
function toCSS(value, indent = '') {
if (typeof value == 'object') {
return `{
${Object.entries(value)
.map(
([key, value]) =>
`${indent} ${key.trim()}${typeof value == 'object' ? '' : ':'} ${toCSS(value, `${indent} `)}`
)
.join('\n')}
${indent}}`;
}
return `${value};`;
}
function addUtilities(utilities) {
for (const [selector, rules] of Object.entries(utilities)) {
css += `
@utility ${selector} ${toCSS(rules)}
`;
}
}
function layoutRule(axis, align, version) {
const alignValue = align == '' ? 'center' : align;
return {
display: 'flex',
'flex-direction': axis == 'y' ? 'column' : 'row',
'align-items': alignValue,
...getVersion('gap', version)
};
}
let css;
function generateLayoutCss() {
css = '';
Object.keys(props).forEach((property) => {
Object.keys(versions).forEach((version) => {
addUtilities({
[`${property}${dash(version)}`]: getVersion(property, version),
[`-${property}${dash(version)}`]: getVersion(property, version, 'calc(-1 * ', ')')
});
});
});
['x', 'y'].forEach((axis) => {
['', 'start', 'end', 'center', 'baseline', 'stretch'].forEach((align) => {
Object.keys(versions).forEach((version) => {
const rule = {
[`layout-${axis}${dash(align)}${dash(version)}`]: layoutRule(axis, align, version)
};
addUtilities(rule);
['m', 'p'].forEach((prop) => {
addUtilities({
[`layout-${axis}-${prop}${dash(align)}${dash(version)}`]: merge(
rule[`layout-${axis}${dash(align)}${dash(version)}`],
getVersion(prop, version)
)
});
});
});
});
const justifies = {
between: 'space-between',
around: 'space-around',
evenly: 'space-evenly'
};
Object.keys(versions).forEach((version) => {
const baseRule = layoutRule(axis, '', version);
Object.entries(justifies).forEach(([name, value]) => {
addUtilities({
[`layout-${axis}-${name}${dash(version)}`]: {
...baseRule,
'justify-content': value
}
});
});
addUtilities({
[`layout-${axis}-wrap${dash(version)}`]: {
...baseRule,
'flex-wrap': 'wrap'
}
});
});
});
Object.keys(versions).forEach((version) => {
const rule = {
display: 'grid',
'grid-template-columns': `repeat(auto-fit, minmax(calc(--value(integer) * var(--spacing)), 1fr))`,
'grid-template-columns ': `repeat(auto-fit, minmax(--value([*]), 1fr))`,
'> *': {
'min-width': 'calc(--value(integer) * var(--spacing))',
'min-width ': '--value([*])'
},
...getVersion('gap', version)
};
addUtilities({
[`layout-grid${dash(version)}-*`]: rule
});
['m', 'p'].forEach((edge) => {
addUtilities({
[`layout-grid-${edge}${dash(version)}`]: merge(
rule,
getVersion(edge + 'x', version),
getVersion(edge + 'y', version)
)
});
});
});
return css;
}
let lastUtilitiesHash = '';
let lastMonacoHash = '';
export default function GenerateLayoutCssPlugin() {
const cwd = process.cwd();
function ensureMonacoAssets() {
const monacoSource = path.resolve(cwd, 'node_modules/monaco-editor/min/vs');
const monacoTarget = path.resolve(cwd, 'static/monaco/vs');
if (!fs.existsSync(monacoSource)) {
return;
}
const targetRoot = path.dirname(monacoTarget);
if (!fs.existsSync(targetRoot)) {
fs.mkdirSync(targetRoot, { recursive: true });
}
const monacoPkg = path.resolve(cwd, 'node_modules/monaco-editor/package.json');
const hash = crypto
.createHash('sha1')
.update(fs.readFileSync(monacoPkg, 'utf-8'))
.digest('hex');
if (hash === lastMonacoHash && fs.existsSync(monacoTarget)) {
return;
}
if (fs.existsSync(monacoTarget)) {
fs.rmSync(monacoTarget, { recursive: true, force: true });
}
fs.cpSync(monacoSource, monacoTarget, { recursive: true });
lastMonacoHash = hash;
console.log(`Copied Monaco assets → ${monacoTarget}`);
}
return {
name: 'convertigo-utilities-css-plugin',
// every environment of SvelteKit 3 starts its build here: the hashes write the files once
buildStart() {
const css = generateLayoutCss();
const outPath = path.resolve(process.cwd(), 'src/convertigo.utilities.css');
const hash = crypto.createHash('sha1').update(css).digest('hex');
if (!fs.existsSync(outPath) || hash !== lastUtilitiesHash) {
fs.writeFileSync(outPath, css, 'utf-8');
lastUtilitiesHash = hash;
console.log(`Generated Convertigo CSS utilities: ${outPath}`);
}
ensureMonacoAssets();
}
};
}