@amaui/style
Version:
CSS in JS styling solution
259 lines (258 loc) • 14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fast_glob_1 = __importDefault(require("fast-glob"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const is_1 = __importDefault(require("@amaui/utils/is"));
const getEnvironment_1 = __importDefault(require("@amaui/utils/getEnvironment"));
const hash_1 = __importDefault(require("@amaui/utils/hash"));
const merge_1 = __importDefault(require("@amaui/utils/merge"));
const stringify_1 = __importDefault(require("@amaui/utils/stringify"));
const to_1 = __importDefault(require("@amaui/utils/to"));
const try_1 = __importDefault(require("@amaui/utils/try"));
const unique_1 = __importDefault(require("@amaui/utils/unique"));
const node_1 = __importDefault(require("@amaui/node"));
const AmauiStyle_1 = __importDefault(require("./AmauiStyle"));
const AmauiTheme_1 = __importDefault(require("./AmauiTheme"));
const AmauiStyleSheetManager_1 = __importDefault(require("./AmauiStyleSheetManager"));
const reset_1 = require("./reset");
const optionsDefault = {
mode: 'regular',
amaui_style: {
get: AmauiStyle_1.default.first.bind(AmauiStyle_1.default),
},
amaui_theme: {
get: AmauiTheme_1.default.first.bind(AmauiTheme_1.default),
},
css: {
file: {
hash: true
},
minify: true
},
html: {
insert: {
comment: '<!-- amaui style insert -->'
},
add: true
},
rule: {
rtl: false,
prefix: true,
sort: true
},
log: true
};
const env = (0, getEnvironment_1.default)();
const getValuePaths = async (value, options = { onlyDirectories: true }) => {
const wd = process.cwd();
let paths = ((0, is_1.default)('array', value) ? value : [value])
.map(item => (item === null || item === void 0 ? void 0 : item.url) || item)
.filter(Boolean)
.filter(item => (0, is_1.default)('string', item))
.map(item => path_1.default.isAbsolute(item) ? item : path_1.default.join(wd, item));
paths = (await (0, fast_glob_1.default)(paths, options))
.map(filePath => path_1.default.resolve(filePath));
return (0, unique_1.default)(paths);
};
const minify = (value) => {
if ((0, is_1.default)('string', value))
return value.replace(/\n/g, '').replace(/ ?(\{|:|,|>|~) ?/g, '$1').replace(/;(\})/g, '$1');
return value;
};
function css(value__, options_ = {}) {
var _a;
const options = (0, merge_1.default)(options_, optionsDefault, { copy: true });
// Amaui style
let amauiStyle = options.amaui_style.value || ((0, is_1.default)('function', options.amaui_style.get) && options.amaui_style.get());
if (amauiStyle === undefined)
amauiStyle = new AmauiStyle_1.default();
// Amaui theme
const amauiTheme = options.amaui_theme.value || ((0, is_1.default)('function', options.amaui_theme.get) && options.amaui_theme.get());
// Make value if it's a function
let value_ = (0, is_1.default)('function', value__) ? (0, try_1.default)(() => value__(amauiTheme)) : value__;
// For reset, add reset to value
let method = 'css';
let priority = 'upper';
if (options.reset) {
method = 'reset';
// Default
const valueDefault = (0, merge_1.default)(reset_1.resetDefault, reset_1.normalize);
// Add reset defaults
// user provided values override reset default values
if ((_a = options.resetProps) === null || _a === void 0 ? void 0 : _a.override)
value_ = Object.assign(Object.assign({}, valueDefault), value_);
else
value_ = (0, merge_1.default)(value_, valueDefault);
}
// reset or pure update priority
if (options.pure)
method = 'pure';
if (options.reset || options.pure)
priority = 'lower';
// Make an instance of amauiStyleSheetManager
const amauiStyleSheetManager = new AmauiStyleSheetManager_1.default(value_, {
mode: options.mode,
pure: options.reset || options.pure,
priority,
amauiTheme,
amauiStyle,
rule: options.rule,
style: {
attributes: {
method
}
}
});
const responseManager = {
ids: amauiStyleSheetManager.ids,
amaui_style_sheet_manager: amauiStyleSheetManager,
sheets: amauiStyleSheetManager.sheets,
add: amauiStyleSheetManager.add.bind(amauiStyleSheetManager),
props: amauiStyleSheetManager.props,
update: amauiStyleSheetManager.update.bind(amauiStyleSheetManager),
remove: amauiStyleSheetManager.remove.bind(amauiStyleSheetManager),
addRule: amauiStyleSheetManager.sheets.static[0] && amauiStyleSheetManager.sheets.static[0].addRule.bind(amauiStyleSheetManager.sheets.static[0]),
};
const response = {
make: async () => {
var _a, _b, _c, _d, _e;
const wd = process.cwd();
// add
const responseManagerValue = responseManager.add();
// All css
let value = amauiStyleSheetManager.css;
const minified = minify(value);
if (options.css.minify)
value = minified;
// CSS
// Make file name, only if at least 1 folder is provided
// and it exists
let made = false;
const paths = {
folders: {
css: await getValuePaths(options.css.folders),
},
files: {
html: await getValuePaths(options.html.files, { onlyFiles: true }),
},
};
const madeFiles = {
css: [],
};
const fileHash = (0, hash_1.default)(minified, { withPrefix: false });
if ((_a = paths.folders.css) === null || _a === void 0 ? void 0 : _a.length) {
const folders = paths.folders.css;
const name = `${((_c = (_b = options.css) === null || _b === void 0 ? void 0 : _b.file) === null || _c === void 0 ? void 0 : _c.name) || env.amaui_methods.makeName.next().value}${((_e = (_d = options.css) === null || _d === void 0 ? void 0 : _d.file) === null || _e === void 0 ? void 0 : _e.hash) ? `.${fileHash}` : ''}.css`;
// Clear folder if clear
const make = async (path_, index) => {
const folder = options.css.folders.find(item => path_ === (path_1.default.isAbsolute(item.url) ? item.url : path_1.default.join(wd, item.url)));
if (folder) {
const clear = folder.clear !== undefined ? folder.clear : options.css.clear;
// Empty folder if clear
if (clear)
await fs_extra_1.default.emptyDir(path_);
// Make the file
const nameWithPath = path_1.default.join(path_, name);
await node_1.default.file.add(nameWithPath, value);
// Add to files
if (index === 0 || !madeFiles.css.length)
madeFiles.css.push(nameWithPath);
if (options.log)
console.log(`Made \x1b[34m${nameWithPath}\x1b[0m \x1b[32m${(0, to_1.default)(value, 'size')}\x1b[0m`);
}
};
// Make files in all the folders
if (options.log)
console.log();
await Promise.all(folders.map((item, index) => make(item, index)));
if (options.log)
console.log();
made = true;
}
// HTML
// Only if css is made and in folders
// and html at least 1 file is provided and it exists
// and html add: true
if (made && paths.files.html.length && options.html.add) {
const files = paths.files.html;
const add = async (path_) => {
var _a, _b, _c, _d;
const file = options.html.files.find(item => path_ === (path_1.default.isAbsolute(item.url) ? item.url : path_1.default.join(wd, item.url)));
if (file) {
// Add path relative from the css file to the index path
const valueHTML = await node_1.default.file.get(path_, false);
const values = valueHTML.split('\n');
const filesRelative = madeFiles.css.map(item => path_1.default.relative(path_1.default.dirname(path_), item));
// Add css files to folders
// Start from insert or file.insert comment or if none exists
// start from the first group of amaui inserted links, or
// start from first the bottom of head
const insert = ((_a = file.insert) === null || _a === void 0 ? void 0 : _a.comment) || ((_c = (_b = options.html) === null || _b === void 0 ? void 0 : _b.insert) === null || _c === void 0 ? void 0 : _c.comment);
const indexInsertComment = values.findIndex(item => item.indexOf(insert) > -1);
const indexAmauiInserts = values.findIndex(item => item.indexOf('<link') > -1 && item.indexOf(`data-amaui='true'`) > -1);
const indexBottomHead = values.findIndex(item => item.indexOf('</head>') > -1);
const indexBottomBody = values.findIndex(item => item.indexOf('</body>') > -1);
const indexStart = ((indexInsertComment > -1 && indexInsertComment + 1) ||
(indexAmauiInserts > -1 && indexAmauiInserts) ||
indexBottomHead);
const inBody = indexStart > indexBottomHead;
// Adding order depends on if it's reset, pure or regular style
const allLinks = values.slice(indexStart, inBody ? indexBottomBody : indexBottomHead).filter(item => item.indexOf('<link') > -1);
const amauiLinks = allLinks.filter(item => item.indexOf(`data-amaui='true'`) > -1);
const amauiLinksPure = amauiLinks.filter(item => item.indexOf(`data-pure='true'`) > -1);
const amauiLinksNoReset = amauiLinks.filter(item => item.indexOf(`data-reset='true'`) === -1);
const amauiLinkReset = values.find(item => item.indexOf('<link') > -1 && item.indexOf(`data-reset='true'`) > -1);
const amauiLinkResetIndex = values.findIndex(item => item === amauiLinkReset);
let indexInsert = amauiLinkResetIndex > -1 ? amauiLinkResetIndex + 1 : indexStart;
if (!!amauiLinksNoReset.length && !options.reset) {
if (!options.pure) {
const amauiLinkLastIndex = values.findIndex(item => item === amauiLinksNoReset[amauiLinksNoReset.length - 1]);
indexInsert = amauiLinkLastIndex + 1;
}
else {
const amauiLinkFirstIndex = values.findIndex(item => item === amauiLinksNoReset[0]);
if (!amauiLinksPure.length)
indexInsert = amauiLinkFirstIndex;
else {
const amauiLinkPureLast = values.findIndex(item => item === amauiLinksPure[amauiLinksPure.length - 1]);
indexInsert = amauiLinkPureLast + 1;
}
}
}
// Take whitespace padding from other styles or links, or title or body + tab space
let padding = '';
const element = values[(inBody ? indexBottomBody : indexBottomHead) - 1];
const main = values[(inBody ? indexBottomBody : indexBottomHead)];
padding = element.split(/(?! )/)[0];
if (padding[0] !== ' ')
padding = main.split(/(?! )/)[0];
if (padding[0] !== ' ')
padding = ' ';
filesRelative.forEach(file_ => values.splice(indexInsert, 0, `${padding}<link rel='stylesheet' href='${file_}' data-amaui='true'${options.reset ? ` data-reset='true'` : ''}${options.pure ? ` data-pure='true'` : ''} />`));
// if not pure and reset
// get names and add (update) as a script global variable to window
// add at the bottom of head
if (((_d = options.html) === null || _d === void 0 ? void 0 : _d.addNames) && !options.pure && !options.reset) {
delete responseManagerValue.ids;
values.splice(indexBottomHead + 1, 0, `${padding}<script>
${padding} if (!window.amauiStyleNames) window.amauiStyleNames = {};
${padding}
${padding} window.amauiStyleNames['${fileHash}'] = ${(0, stringify_1.default)(responseManagerValue, padding.length + 2)};
${padding}</script>`);
}
// Update the file
await node_1.default.file.update(path_, values.join('\n'));
}
};
await Promise.all(files.map(item => add(item)));
}
},
};
// Response
return response;
}
exports.default = css;