UNPKG

unocss-preset-weapp

Version:

the unocss preset for wechat miniprogram (uniapp, taro)

170 lines (164 loc) 5.94 kB
import { createFilter } from '@rollup/pluginutils'; import { transformCode, getClass } from 'unplugin-transform-class/utils'; export { defaultRules } from 'unplugin-transform-class/utils'; import { extractorAttributify as extractorAttributify$1 } from 'unplugin-attributify-to-class/utils'; export { defaultAttributes, defaultIgnoreNonValuedAttributes } from 'unplugin-attributify-to-class/utils'; const variantsRE = /^(?!.*\[[^:]+:.+\]$)((?:.+:)?!?)(.*)$/; const elementRE = /(<\w[\w:.$-]*\s)((?:'[^>']*'|"[^>"]*"|`[^>`]*`|\{[^>}]*\}|[^>]*?)*)/g; const valuedAttributeRE = /(\?|(?!\d|-{2}|-\d)[\w\u00A0-\uFFFF-:%]+)(?:=("[^"]*|'[^']*))?/g; const splitterRE = /[\s'"`;>]+/; function autocompleteExtractorAttributify(options) { return { name: "weapp-attributify", extract: ({ content, cursor }) => { const matchedElements = content.matchAll(elementRE); 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); 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.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.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) }; } }; } }; } function presetWeappAttributify(options) { return { name: "unocss-preset-weapp-attributify", autocomplete: { extractors: [autocompleteExtractorAttributify(options)] } }; } function transformer(options = {}) { const idFilter = createFilter( options.include || [/\.vue$/, /\.vue\?vue/], options.exclude || [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/] ); const extractor = extractorAttributify$1(options); return { name: "transformer-weapp-attributify", idFilter, enforce: "pre", transform(code) { const newCode = extractor(code.toString()); code.overwrite(0, code.original.length, newCode); } }; } function extractorAttributify(options = {}) { return { transformerAttributify: () => transformer(options), presetWeappAttributify: () => presetWeappAttributify(options) }; } const transformerAttributify = transformer; const defaultOptions = { classTags: true, include: [/\.[jt]sx?$/, /\.vue$/, /\.vue\?vue/], exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/] }; function transformerClass(options = {}) { options = { ...defaultOptions, ...options }; const idFilter = createFilter( options.include, options.exclude ); const vueFilter = createFilter( [/\.vue$/, /\.vue\?vue/] ); return { name: "transformer-weapp-class", idFilter, enforce: "pre", transform(code, id) { let newCode = transformCode(code.toString(), options.transformRules); if (options.classTags) { const classNames = getClass(code.toString()); const injectStr = Array.from(new Set(classNames.map((x) => x[1]).filter((x) => x).flatMap((x) => x.split(" ")))).join(" "); if (vueFilter(id)) newCode = newCode.replace("<template>", `<template> <!-- ${injectStr} --> `); else newCode = `/* ${injectStr} */ ${newCode}`; } code.overwrite(0, code.original.length, newCode); } }; } export { extractorAttributify, transformerAttributify, transformerClass };