feature: vor und nachteile

This commit is contained in:
Hikyu
2026-05-31 13:54:31 +02:00
parent 552a947a1c
commit e3dad17446
23270 changed files with 3024794 additions and 200 deletions
+89
View File
@@ -0,0 +1,89 @@
import * as _unocss_core from '@unocss/core';
import { PresetOptions, AutoCompleteExtractor, Extractor, VariantObject } from '@unocss/core';
interface AttributifyOptions extends PresetOptions {
/**
* Only generate CSS for attributify or class
*
* @default false
*/
strict?: boolean;
/**
* @default 'un-'
*/
prefix?: string;
/**
* Only match for prefixed attributes
*
* @default false
*/
prefixedOnly?: boolean;
/**
* Support matching non-valued attributes
*
* For example
* ```html
* <div mt-2 />
* ```
*
* @default true
*/
nonValuedAttribute?: boolean;
/**
* A list of attributes to be ignored from extracting.
*/
ignoreAttributes?: string[];
/**
* Non-valued attributes will also match if the actual value represented in DOM is `true`.
* This option exists for supporting frameworks that encodes non-valued attributes as `true`.
* Enabling this option will break rules that ends with `true`.
*
* @default false
*/
trueToNonValued?: boolean;
}
declare function autocompleteExtractorAttributify(options?: AttributifyOptions): AutoCompleteExtractor;
declare const defaultIgnoreAttributes: string[];
declare function extractorAttributify(options?: AttributifyOptions): Extractor;
type TwoStringsCompositionPrefix = 'm' | 'p';
type TwoStringsCompositionSuffix = 'r' | 'b' | 'l' | 't' | 'a' | 'x' | 'y';
/** Some words can compose with two strings to become a complete unocss rule such as ha, mr, mb */
type TwoStringsComposition = `${TwoStringsCompositionPrefix}${TwoStringsCompositionSuffix}` | 'ha' | 'wa';
/** Some words can be a complete unocss rule by itself */
type SpecialSingleWord = 'container' | 'flex' | 'block' | 'inline' | 'table' | 'isolate' | 'absolute' | 'relative' | 'fixed' | 'sticky' | 'static' | 'visible' | 'invisible' | 'grow' | 'shrink' | 'antialiased' | 'italic' | 'ordinal' | 'overline' | 'underline' | 'uppercase' | 'lowercase' | 'capitalize' | 'truncate' | 'border' | 'rounded' | 'outline' | 'ring' | 'shadow' | 'blur' | 'grayscale' | 'invert' | 'sepia' | 'transition' | 'resize' | 'transform' | 'filter';
type PseudoPrefix = 'active' | 'before' | 'after' | 'dark' | 'light' | 'first' | 'last' | 'focus' | 'hover' | 'link' | 'root' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'enabled' | 'disabled' | 'all' | 'children';
/** Some words can be used to separate utilities, such as font="mono light", text="sm white" */
type SeparateEnabled = 'align' | 'animate' | 'backdrop' | 'bg' | 'blend' | 'border' | 'box' | 'container' | 'content' | 'cursor' | 'display' | 'divide' | 'filter' | 'flex' | 'font' | 'fw' | 'gap' | 'gradient' | 'grid' | 'h' | 'icon' | 'items' | 'justify' | 'list' | 'm' | 'op' | 'opacity' | 'order' | 'outline' | 'overflow' | 'p' | 'place' | 'pos' | 'position' | 'ring' | 'select' | 'shadow' | 'size' | 'space' | 'table' | 'text' | 'transform' | 'transition' | 'underline' | 'w' | 'z' | PseudoPrefix;
type BasicAttributes = SpecialSingleWord | TwoStringsComposition | SeparateEnabled;
type AttributifyNames<Prefix extends string = ''> = `${Prefix}${BasicAttributes}` | `${Prefix}${PseudoPrefix}:${BasicAttributes}`;
interface AttributifyAttributes extends Partial<Record<AttributifyNames, string | boolean>> {
}
declare const variantsRE: RegExp;
declare function variantAttributify(options?: AttributifyOptions): VariantObject;
/**
* This enables the attributify mode for other presets.
*
* @example
*
* ```html
* <button
* bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
* text="sm white"
* font="mono light"
* p="y-2 x-4"
* border="2 rounded blue-200"
* >
* Button
* </button>
* ```
*
* @see https://unocss.dev/presets/attributify
*/
declare const presetAttributify: _unocss_core.PresetFactory<object, AttributifyOptions>;
export { type AttributifyAttributes, type AttributifyNames, type AttributifyOptions, type BasicAttributes, type PseudoPrefix, type SeparateEnabled, type SpecialSingleWord, type TwoStringsComposition, type TwoStringsCompositionPrefix, type TwoStringsCompositionSuffix, autocompleteExtractorAttributify, presetAttributify as default, defaultIgnoreAttributes, extractorAttributify, presetAttributify, variantAttributify, variantsRE };
+89
View File
@@ -0,0 +1,89 @@
import * as _unocss_core from '@unocss/core';
import { PresetOptions, AutoCompleteExtractor, Extractor, VariantObject } from '@unocss/core';
interface AttributifyOptions extends PresetOptions {
/**
* Only generate CSS for attributify or class
*
* @default false
*/
strict?: boolean;
/**
* @default 'un-'
*/
prefix?: string;
/**
* Only match for prefixed attributes
*
* @default false
*/
prefixedOnly?: boolean;
/**
* Support matching non-valued attributes
*
* For example
* ```html
* <div mt-2 />
* ```
*
* @default true
*/
nonValuedAttribute?: boolean;
/**
* A list of attributes to be ignored from extracting.
*/
ignoreAttributes?: string[];
/**
* Non-valued attributes will also match if the actual value represented in DOM is `true`.
* This option exists for supporting frameworks that encodes non-valued attributes as `true`.
* Enabling this option will break rules that ends with `true`.
*
* @default false
*/
trueToNonValued?: boolean;
}
declare function autocompleteExtractorAttributify(options?: AttributifyOptions): AutoCompleteExtractor;
declare const defaultIgnoreAttributes: string[];
declare function extractorAttributify(options?: AttributifyOptions): Extractor;
type TwoStringsCompositionPrefix = 'm' | 'p';
type TwoStringsCompositionSuffix = 'r' | 'b' | 'l' | 't' | 'a' | 'x' | 'y';
/** Some words can compose with two strings to become a complete unocss rule such as ha, mr, mb */
type TwoStringsComposition = `${TwoStringsCompositionPrefix}${TwoStringsCompositionSuffix}` | 'ha' | 'wa';
/** Some words can be a complete unocss rule by itself */
type SpecialSingleWord = 'container' | 'flex' | 'block' | 'inline' | 'table' | 'isolate' | 'absolute' | 'relative' | 'fixed' | 'sticky' | 'static' | 'visible' | 'invisible' | 'grow' | 'shrink' | 'antialiased' | 'italic' | 'ordinal' | 'overline' | 'underline' | 'uppercase' | 'lowercase' | 'capitalize' | 'truncate' | 'border' | 'rounded' | 'outline' | 'ring' | 'shadow' | 'blur' | 'grayscale' | 'invert' | 'sepia' | 'transition' | 'resize' | 'transform' | 'filter';
type PseudoPrefix = 'active' | 'before' | 'after' | 'dark' | 'light' | 'first' | 'last' | 'focus' | 'hover' | 'link' | 'root' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'enabled' | 'disabled' | 'all' | 'children';
/** Some words can be used to separate utilities, such as font="mono light", text="sm white" */
type SeparateEnabled = 'align' | 'animate' | 'backdrop' | 'bg' | 'blend' | 'border' | 'box' | 'container' | 'content' | 'cursor' | 'display' | 'divide' | 'filter' | 'flex' | 'font' | 'fw' | 'gap' | 'gradient' | 'grid' | 'h' | 'icon' | 'items' | 'justify' | 'list' | 'm' | 'op' | 'opacity' | 'order' | 'outline' | 'overflow' | 'p' | 'place' | 'pos' | 'position' | 'ring' | 'select' | 'shadow' | 'size' | 'space' | 'table' | 'text' | 'transform' | 'transition' | 'underline' | 'w' | 'z' | PseudoPrefix;
type BasicAttributes = SpecialSingleWord | TwoStringsComposition | SeparateEnabled;
type AttributifyNames<Prefix extends string = ''> = `${Prefix}${BasicAttributes}` | `${Prefix}${PseudoPrefix}:${BasicAttributes}`;
interface AttributifyAttributes extends Partial<Record<AttributifyNames, string | boolean>> {
}
declare const variantsRE: RegExp;
declare function variantAttributify(options?: AttributifyOptions): VariantObject;
/**
* This enables the attributify mode for other presets.
*
* @example
*
* ```html
* <button
* bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
* text="sm white"
* font="mono light"
* p="y-2 x-4"
* border="2 rounded blue-200"
* >
* Button
* </button>
* ```
*
* @see https://unocss.dev/presets/attributify
*/
declare const presetAttributify: _unocss_core.PresetFactory<object, AttributifyOptions>;
export { type AttributifyAttributes, type AttributifyNames, type AttributifyOptions, type BasicAttributes, type PseudoPrefix, type SeparateEnabled, type SpecialSingleWord, type TwoStringsComposition, type TwoStringsCompositionPrefix, type TwoStringsCompositionSuffix, autocompleteExtractorAttributify, presetAttributify as default, defaultIgnoreAttributes, extractorAttributify, presetAttributify, variantAttributify, variantsRE };
+217
View File
@@ -0,0 +1,217 @@
import { isAttributifySelector, isValidSelector, definePreset } from '@unocss/core';
const variantsRE = /^(?!.*\[[^:]+:.+\]$)((?:.+:)?!?)(.*)$/;
function variantAttributify(options = {}) {
const prefix = options.prefix ?? "un-";
const prefixedOnly = options.prefixedOnly ?? false;
const trueToNonValued = options.trueToNonValued ?? false;
let variantsValueRE;
return {
name: "attributify",
match(input, { generator }) {
const match = isAttributifySelector(input);
if (!match)
return;
let name = match[1];
if (name.startsWith(prefix))
name = name.slice(prefix.length);
else if (prefixedOnly)
return;
const content = match[2];
const [, variants = "", body = content] = content.match(variantsRE) || [];
if (body === "~" || trueToNonValued && body === "true" || !body) {
return `${variants}${name}`;
}
if (variantsValueRE == null) {
const separators = generator?.config?.separators?.join("|");
if (separators)
variantsValueRE = new RegExp(`^(.*\\](?:${separators}))(\\[[^\\]]+?\\])$`);
else
variantsValueRE = false;
}
if (variantsValueRE) {
const [, bodyVariant, bracketValue] = content.match(variantsValueRE) || [];
if (bracketValue)
return `${bodyVariant}${variants}${name}-${bracketValue}`;
}
if (variants && body.match(/^[\d.]+$/)) {
const variantParts = variants.split(/([^:]*:)/g).filter(Boolean);
const _body = variantParts.pop() + body;
const _variants = variantParts.join("");
return [
{ matcher: `${variants}${name}-${body}` },
{ matcher: `${_variants}${name}-${_body}` }
];
}
return `${variants}${name}-${body}`;
}
};
}
const elementRE$1 = /(<\w[\w:.$-]*\s)((?:'[^>']*'|"[^>"]*"|`[^>`]*`|\{[^>}]*\}|[^>]*?)*)/g;
const valuedAttributeRE$1 = /(\?|(?!\d|-{2}|-\d)[\w\u00A0-\uFFFF-:%]+)(?:=("[^"]*|'[^']*))?/g;
const splitterRE$1 = /[\s'"`;>]+/;
function autocompleteExtractorAttributify(options) {
return {
name: "attributify",
extract: ({ content, cursor }) => {
const matchedElements = content.matchAll(elementRE$1);
let attrs;
let elPos = 0;
for (const match of matchedElements) {
const [, prefix, content2] = match;
const currentPos2 = match.index + prefix.length;
if (cursor > currentPos2 && cursor <= currentPos2 + content2.length) {
elPos = currentPos2;
attrs = content2;
break;
}
}
if (!attrs)
return null;
const matchedAttributes = attrs.matchAll(valuedAttributeRE$1);
let attrsPos = 0;
let attrName;
let attrValues;
for (const match of matchedAttributes) {
const [matched, name, rawValues] = match;
const currentPos2 = elPos + match.index;
if (cursor > currentPos2 && cursor <= currentPos2 + matched.length) {
attrsPos = currentPos2;
attrName = name;
attrValues = rawValues?.slice(1);
break;
}
}
if (!attrName)
return null;
if (attrName === "class" || attrName === "className" || attrName === ":class")
return null;
const hasPrefix = !!options?.prefix && attrName.startsWith(options.prefix);
if (options?.prefixedOnly && !hasPrefix)
return null;
const attrNameWithoutPrefix = hasPrefix ? attrName.slice(options.prefix.length) : attrName;
if (attrValues === void 0) {
return {
extracted: attrNameWithoutPrefix,
resolveReplacement(suggestion) {
const startOffset = hasPrefix ? options.prefix.length : 0;
return {
start: attrsPos + startOffset,
end: attrsPos + attrName.length,
replacement: suggestion
};
}
};
}
const attrValuePos = attrsPos + attrName.length + 2;
let matchSplit = splitterRE$1.exec(attrValues);
let currentPos = 0;
let value;
while (matchSplit) {
const [matched] = matchSplit;
if (cursor > attrValuePos + currentPos && cursor <= attrValuePos + currentPos + matchSplit.index) {
value = attrValues.slice(currentPos, currentPos + matchSplit.index);
break;
}
currentPos += matchSplit.index + matched.length;
matchSplit = splitterRE$1.exec(attrValues.slice(currentPos));
}
if (value === void 0)
value = attrValues.slice(currentPos);
const [, variants = "", body] = value.match(variantsRE) || [];
return {
extracted: `${variants}${attrNameWithoutPrefix}-${body}`,
transformSuggestions(suggestions) {
return suggestions.filter((v) => v.startsWith(`${variants}${attrNameWithoutPrefix}-`)).map((v) => variants + v.slice(variants.length + attrNameWithoutPrefix.length + 1));
},
resolveReplacement(suggestion) {
return {
start: currentPos + attrValuePos,
end: currentPos + attrValuePos + value.length,
replacement: variants + suggestion.slice(variants.length + attrNameWithoutPrefix.length + 1)
};
}
};
}
};
}
const strippedPrefixes = [
"v-bind:",
":"
];
const splitterRE = /[\s'"`;]+/g;
const elementRE = /<[^>\s]*\s((?:'[^']*'|"[^"]*"|`[^`]*`|\{[^}]*\}|=>|[^>]*?)*)/g;
const valuedAttributeRE = /(\?|(?!\d|-{2}|-\d)[\w\u00A0-\uFFFF:!%.~<-]+)=?(?:"([^"]*)"|'([^']*)'|\{([^}]*)\})?/g;
const defaultIgnoreAttributes = ["placeholder", "fill", "opacity", "stroke-opacity"];
function extractorAttributify(options) {
const ignoreAttributes = options?.ignoreAttributes ?? defaultIgnoreAttributes;
const nonValuedAttribute = options?.nonValuedAttribute ?? true;
const trueToNonValued = options?.trueToNonValued ?? false;
return {
name: "@unocss/preset-attributify/extractor",
extract({ code }) {
return Array.from(code.matchAll(elementRE)).flatMap((match) => Array.from((match[1] || "").matchAll(valuedAttributeRE))).flatMap(([, name, ...contents]) => {
const content = contents.filter(Boolean).join("");
if (ignoreAttributes.includes(name))
return [];
for (const prefix of strippedPrefixes) {
if (name.startsWith(prefix)) {
name = name.slice(prefix.length);
break;
}
}
if (!content) {
if (isValidSelector(name) && nonValuedAttribute !== false) {
const result = [`[${name}=""]`];
if (trueToNonValued)
result.push(`[${name}="true"]`);
return result;
}
return [];
}
if (["class", "className"].includes(name)) {
return content.split(splitterRE).filter(isValidSelector);
} else if (elementRE.test(content)) {
elementRE.lastIndex = 0;
return this.extract({ code: content });
} else {
if (options?.prefixedOnly && options.prefix && !name.startsWith(options.prefix))
return [];
return content.split(splitterRE).filter((v) => Boolean(v) && v !== ":").map((v) => `[${name}~="${v}"]`);
}
});
}
};
}
const presetAttributify = definePreset((options = {}) => {
options.strict = options.strict ?? false;
options.prefix = options.prefix ?? "un-";
options.prefixedOnly = options.prefixedOnly ?? false;
options.nonValuedAttribute = options.nonValuedAttribute ?? true;
options.ignoreAttributes = options.ignoreAttributes ?? defaultIgnoreAttributes;
const variants = [
variantAttributify(options)
];
const extractors = [
extractorAttributify(options)
];
const autocompleteExtractors = [
autocompleteExtractorAttributify(options)
];
return {
name: "@unocss/preset-attributify",
enforce: "post",
variants,
extractors,
options,
autocomplete: {
extractors: autocompleteExtractors
},
extractorDefault: options.strict ? false : void 0
};
});
export { autocompleteExtractorAttributify, presetAttributify as default, defaultIgnoreAttributes, extractorAttributify, presetAttributify, variantAttributify, variantsRE };