styimat 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +317 -0
- package/convert-styimat.js +89 -0
- package/package.json +40 -0
- package/styimat.js +1166 -0
- package/styimat.min.js +1 -0
package/styimat.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const styimat=function(){let defaultConfig={rootSelector:":root",variablePrefix:"--",preserveOriginal:false,indentSize:2,enableNesting:true,autoProcessStyleTags:true,styleTagAttribute:"e",convertLabToRGB:true,convertLchToRGB:true,enableP3:true};let p3Supported=null;function detectP3Support(){if(p3Supported!==null)return p3Supported;if(typeof window==="undefined"||!window.CSS){p3Supported=false;return false}try{p3Supported=CSS.supports("color","color(display-p3 1 0 0)")}catch(error){console.warn("P3支持检测失败:",error);p3Supported=false}return p3Supported}function parseSingleLineCSS(cssString){let str=cssString.trim();if(str.endsWith(";")){str=str.slice(0,-1)}if(!str){return[]}const declarations=[];let currentDeclaration="";let inParens=0;let inQuotes=false;let quoteChar="";for(let i=0;i<str.length;i++){const char=str[i];if((char==='"'||char==="'")&&!inQuotes){inQuotes=true;quoteChar=char}else if(char===quoteChar&&inQuotes){inQuotes=false;quoteChar=""}if(!inQuotes){if(char==="("){inParens++}else if(char===")"){inParens--}}if(char===";"&&!inQuotes&&inParens===0){if(currentDeclaration.trim()){declarations.push(currentDeclaration.trim());currentDeclaration=""}}else{currentDeclaration+=char}}if(currentDeclaration.trim()){declarations.push(currentDeclaration.trim())}const result=[];for(const declaration of declarations){if(!declaration.trim())continue;const colonIndex=findFirstColonOutsideQuotes(declaration);if(colonIndex===-1){console.warn(`无效的CSS声明: "${declaration}"`);continue}const property=declaration.substring(0,colonIndex).trim();let value=declaration.substring(colonIndex+1).trim();if(value.endsWith(";")){value=value.slice(0,-1).trim()}result.push({[property]:value})}return result}function findFirstColonOutsideQuotes(str){let inQuotes=false;let quoteChar="";for(let i=0;i<str.length;i++){const char=str[i];if((char==='"'||char==="'")&&!inQuotes){inQuotes=true;quoteChar=char}else if(char===quoteChar&&inQuotes){inQuotes=false;quoteChar=""}if(char===":"&&!inQuotes){return i}}return-1}function convertAllLabLchColors(cssValue,config){if(!config.convertLabToRGB&&!config.convertLchToRGB){return cssValue}let result=cssValue;result=parseHexColorFormats(result,config);const colorFunctionRegex=/(lab|lch)\([^)]+\)/gi;const processedColors=new Map;const processColorFunctions=str=>str.replace(colorFunctionRegex,match=>{if(processedColors.has(match)){return processedColors.get(match)}let converted=match;if(match.toLowerCase().startsWith("lab(")){if(config.convertLabToRGB){converted=convertSingleLabColor(match,config)}}else if(match.toLowerCase().startsWith("lch(")){if(config.convertLchToRGB){converted=convertSingleLchColor(match,config)}}processedColors.set(match,converted);return converted});let lastResult;do{lastResult=result;result=processColorFunctions(result)}while(result!==lastResult);return result}function parseHexColorFormats(value,config){let result=value;const hexLabRegex=/lab#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/gi;const hexLchRegex=/lch#([0-9a-f]{2})([0-9a-f]{2})(\d{1,3})/gi;const processedHexColors=new Map;result=result.replace(hexLabRegex,(match,L_hex,A_hex,B_hex)=>{if(processedHexColors.has(match)){return processedHexColors.get(match)}try{const L=parseInt(L_hex,16)/255*100;const A=(parseInt(A_hex,16)-128)*1.5;const B=(parseInt(B_hex,16)-128)*1.5;const converted=generateColorString(L,A,B,config);processedHexColors.set(match,converted);return converted}catch(error){console.warn(`无法解析lab#十六进制颜色: ${match}`,error);return match}});result=result.replace(hexLchRegex,(match,L_hex,C_hex,H_dec)=>{if(processedHexColors.has(match)){return processedHexColors.get(match)}try{const L=parseInt(L_hex,16)/255*100;const C=parseInt(C_hex,16)/255*150;const H=parseInt(H_dec)/100*360;const lab=lchToLab(L,C,H);const converted=generateColorString(lab.L,lab.a,lab.b,config);processedHexColors.set(match,converted);return converted}catch(error){console.warn(`无法解析lch#十六进制颜色: ${match}`,error);return match}});return result}function convertSingleLabColor(labString,config){const labRegex=/lab\(\s*([\d.]+)(%?)\s+([\d.-]+)\s+([\d.-]+)(?:\s*\/\s*([\d.%]+))?\s*\)/i;const match=labString.match(labRegex);if(!match){return labString}try{let L=parseFloat(match[1]);if(match[2]==="%"){L=L}else{if(L<0)L=0;if(L>100)L=100}const A=parseFloat(match[3]);const B=parseFloat(match[4]);const alphaValue=match[5]!==undefined?match[5].includes("%")?parseFloat(match[5])/100:parseFloat(match[5]):null;return generateColorString(L,A,B,config,alphaValue)}catch(error){console.warn(`无法转换LAB颜色: ${labString}`,error);return labString}}function convertSingleLchColor(lchString,config){const lchRegex=/lch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)(deg)?(?:\s*\/\s*([\d.%]+))?\s*\)/i;const match=lchString.match(lchRegex);if(!match){return lchString}try{let L=parseFloat(match[1]);if(match[2]==="%"){L=L}else{if(L<0)L=0;if(L>100)L=100}const C=parseFloat(match[3]);let H=parseFloat(match[4]);if(C<0){console.warn(`LCH中的C值不能为负: ${C}`)}H=(H%360+360)%360;const lab=lchToLab(L,C,H);const alphaValue=match[6]!==undefined?match[6].includes("%")?parseFloat(match[6])/100:parseFloat(match[6]):null;return generateColorString(lab.L,lab.a,lab.b,config,alphaValue)}catch(error){console.warn(`无法转换LCH颜色: ${lchString}`,error);return lchString}}function lchToLab(L,C,H){const H_rad=H*Math.PI/180;const a=C*Math.cos(H_rad);const b=C*Math.sin(H_rad);return{L:L,a:a,b:b}}function preciseLabToRGB(L,a,b){const labToXyz=(L,a,b)=>{const refX=.95047;const refY=1;const refZ=1.08883;const epsilon=.008856;const kappa=903.3;const fy=(L+16)/116;const fx=a/500+fy;const fz=fy-b/200;const xr=fx**3>epsilon?fx**3:(116*fx-16)/kappa;const yr=L>kappa*epsilon?((L+16)/116)**3:L/kappa;const zr=fz**3>epsilon?fz**3:(116*fz-16)/kappa;return[xr*refX,yr*refY,zr*refZ]};const xyzToLinearRgb=(x,y,z)=>{const M=[[3.2404542,-1.5371385,-.4985314],[-.969266,1.8760108,.041556],[.0556434,-.2040259,1.0572252]];const r=M[0][0]*x+M[0][1]*y+M[0][2]*z;const g=M[1][0]*x+M[1][1]*y+M[1][2]*z;const b=M[2][0]*x+M[2][1]*y+M[2][2]*z;return[r,g,b]};const applyGamma=c=>{const sign=c<0?-1:1;const absC=Math.abs(c);if(absC<=.0031308){return sign*12.92*absC}else{return sign*(1.055*Math.pow(absC,1/2.4)-.055)}};const clamp=value=>Math.max(0,Math.min(255,Math.round(value*255)));const[X,Y,Z]=labToXyz(L,a,b);const[linearR,linearG,linearB]=xyzToLinearRgb(X,Y,Z);const r=applyGamma(linearR);const g=applyGamma(linearG);const bOut=applyGamma(linearB);return{r:clamp(r),g:clamp(g),b:clamp(bOut)}}function labToP3(L,a,b){const labToXyz=(L,a,b)=>{const refX=.95047;const refY=1;const refZ=1.08883;const epsilon=.008856;const kappa=903.3;const fy=(L+16)/116;const fx=a/500+fy;const fz=fy-b/200;const xr=fx**3>epsilon?fx**3:(116*fx-16)/kappa;const yr=L>kappa*epsilon?((L+16)/116)**3:L/kappa;const zr=fz**3>epsilon?fz**3:(116*fz-16)/kappa;return[xr*refX,yr*refY,zr*refZ]};const xyzToLinearP3=(x,y,z)=>{const M=[[2.493496911941425,-.9313836179191239,-.40271078445071684],[-.8294889695615747,1.7626640603183463,.023624685841943577],[.03584583024378447,-.07617238926804182,.9568845240076872]];const r=M[0][0]*x+M[0][1]*y+M[0][2]*z;const g=M[1][0]*x+M[1][1]*y+M[1][2]*z;const b=M[2][0]*x+M[2][1]*y+M[2][2]*z;return[r,g,b]};const applyGamma=c=>{const sign=c<0?-1:1;const absC=Math.abs(c);if(absC<=.0031308){return sign*12.92*absC}else{return sign*(1.055*Math.pow(absC,1/2.4)-.055)}};const clamp=value=>Math.max(0,Math.min(255,Math.round(value*255)));try{const[X,Y,Z]=labToXyz(L,a,b);const[linearR,linearG,linearB]=xyzToLinearP3(X,Y,Z);const r=applyGamma(linearR);const g=applyGamma(linearG);const bOut=applyGamma(linearB);return{r:Math.max(0,Math.min(1,r)),g:Math.max(0,Math.min(1,g)),b:Math.max(0,Math.min(1,bOut))}}catch(error){console.warn("P3转换失败:",error);const rgb=preciseLabToRGB(L,a,b);return{r:rgb.r/255,g:rgb.g/255,b:rgb.b/255}}}function generateColorString(L,a,b,config,alpha=null){if(!config.enableP3||!detectP3Support()){const rgb=preciseLabToRGB(L,a,b);if(alpha!==null){return`rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`}return`rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`}else{const p3=labToP3(L,a,b);if(alpha!==null){return`color(display-p3 ${p3.r.toFixed(4)} ${p3.g.toFixed(4)} ${p3.b.toFixed(4)} / ${alpha})`}return`color(display-p3 ${p3.r.toFixed(4)} ${p3.g.toFixed(4)} ${p3.b.toFixed(4)})`}}function processCSSValue(value,config){return convertAllLabLchColors(value,config)}function extractVariablesAndCSS(cssText,config){const lines=cssText.split("\n");const globalVariables={};const selectorVariables=new Map;let cssWithoutVars="";let currentSelector=null;let inSelectorBlock=false;let currentIndent=0;for(let line of lines){const trimmed=line.trim();const varMatch=trimmed.match(/^\$([a-zA-Z0-9_-]+)\s*:\s*(.+?);?$/);if(varMatch){const[,varName,varValue]=varMatch;const processedValue=convertAllLabLchColors(replaceVariableUsesInValue(varValue.trim(),{...globalVariables,...currentSelector?selectorVariables.get(currentSelector)||{}:{}}),config);if(currentSelector){if(!selectorVariables.has(currentSelector)){selectorVariables.set(currentSelector,{})}selectorVariables.get(currentSelector)[varName]=processedValue}else{globalVariables[varName]=processedValue}continue}if(trimmed.endsWith("{")){currentSelector=trimmed.slice(0,-1).trim();inSelectorBlock=true;cssWithoutVars+=line+"\n";continue}if(trimmed==="}"){if(inSelectorBlock){if(currentSelector&&selectorVariables.has(currentSelector)){const vars=selectorVariables.get(currentSelector);const indent=" ".repeat(currentIndent);for(const[varName,varValue]of Object.entries(vars)){cssWithoutVars+=`${indent} --${varName}: ${varValue};\n`}}}inSelectorBlock=false;currentSelector=null}cssWithoutVars+=line+"\n";if(line.includes("{")){currentIndent+=2}if(line.includes("}")){currentIndent=Math.max(0,currentIndent-2)}}return{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars.trim()}}function parseNestedRules(cssText,config){const lines=cssText.split("\n");const stack=[];const rootRules=[];let currentIndent=0;for(let i=0;i<lines.length;i++){const line=lines[i];const trimmed=line.trim();if(!trimmed)continue;const indent=line.match(/^(\s*)/)[0].length;const indentLevel=Math.floor(indent/config.indentSize);if(trimmed==="}"){if(stack.length>0){const rule=stack.pop();if(stack.length>0){const parent=stack[stack.length-1];if(!parent.children)parent.children=[];parent.children.push(rule)}else{rootRules.push(rule)}}continue}if(trimmed.endsWith("{")){const selector=trimmed.slice(0,-1).trim();const rule={selector:selector,properties:[],children:[],indentLevel:indentLevel};stack.push(rule);continue}if(!trimmed.includes("{")&&!trimmed.includes("}")&&trimmed.includes(":")){if(stack.length>0){const currentRule=stack[stack.length-1];const parsed=parseSingleLineCSS(trimmed);parsed.forEach(obj=>{const key=Object.keys(obj)[0];const value=convertAllLabLchColors(obj[key],config);currentRule.properties.push(`${key}: ${value}`)})}continue}}while(stack.length>0){const rule=stack.pop();if(stack.length===0){rootRules.push(rule)}else{const parent=stack[stack.length-1];if(!parent.children)parent.children=[];parent.children.push(rule)}}return convertRulesToCSS(rootRules,config)}function convertRulesToCSS(rules,config,parentSelector=""){let result="";const isParentAt=parentSelector.startsWith("@");for(const rule of rules){const isAt=rule.selector.startsWith("@");let fullSelector=(isParentAt?" ":"")+rule.selector;if(isAt){fullSelector=rule.selector+" {\n"}if(parentSelector){if(fullSelector.includes("&")){fullSelector=fullSelector.replace(/&/g,parentSelector)}else if(fullSelector.trim().startsWith(":")){fullSelector=parentSelector+fullSelector}else{fullSelector=parentSelector+(isParentAt?"":" ")+fullSelector}}if(rule.properties.length>0){result+=(isAt?"":fullSelector)+" {\n";for(const prop of rule.properties){const parsed=parseSingleLineCSS(prop);parsed.forEach(obj=>{const key=Object.keys(obj)[0];const value=convertAllLabLchColors(obj[key],config);result+=(isParentAt?" ":"")+` ${key}: ${value};\n`})}result+=isParentAt?" }\n":"}\n\n"}if(rule.children&&rule.children.length>0){result+=convertRulesToCSS(rule.children,config,fullSelector)}if(isParentAt){result+="}\n\n"}}return result.trim()+(isParentAt?"\n\n":"")}function replaceVariableUsesInValue(value,variables){return value.replace(/\$([a-zA-Z0-9_-]+)/g,(match,varName)=>{if(variables[varName]){return`var(--${varName})`}return match})}function replaceVariableUses(cssText,globalVariables,selectorVariables,config){let result=cssText;for(const[varName,varValue]of Object.entries(globalVariables)){const varRegex=new RegExp(`\\$${varName}(?![a-zA-Z0-9_-])`,"g");result=result.replace(varRegex,`var(--${varName})`)}result=result.replace(/\$([a-zA-Z0-9_-]+)/g,(match,varName)=>`var(--${varName})`);if(config.convertLabToRGB||config.convertLchToRGB){result=convertAllLabLchColors(result,config)}return result}function generateRootRule(variables,config){if(Object.keys(variables).length===0){return""}const declarations=Object.entries(variables).map(([name,value])=>{const processedValue=convertAllLabLchColors(replaceVariableUsesInValue(value,variables),config);return` --${name}: ${processedValue};`}).join("\n");return`${config.rootSelector} {\n${declarations}\n}\n\n`}function injectSelectorVariables(cssText,selectorVariables,config){let result="";const lines=cssText.split("\n");let currentSelector=null;for(let line of lines){const trimmed=line.trim();if(trimmed.endsWith("{")){currentSelector=trimmed.slice(0,-1).trim()}if(trimmed==="}"&¤tSelector){if(selectorVariables.has(currentSelector)){const vars=selectorVariables.get(currentSelector);const indent=line.match(/^(\s*)/)[0];for(const[varName,varValue]of Object.entries(vars)){result+=indent+" --"+varName+": "+varValue+";\n"}}currentSelector=null}if(config.convertLabToRGB||config.convertLchToRGB){result+=convertAllLabLchColors(line,config)+"\n"}else{result+=line+"\n"}}return result.trim()}function convert(cssText,customConfig={}){const config={...defaultConfig,...customConfig};const{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars}=extractVariablesAndCSS(cssText,config);let processedCSS=cssWithoutVars.trim();if(config.enableNesting&&cssWithoutVars.includes("{")){try{processedCSS=parseNestedRules(cssWithoutVars,config)}catch(error){console.warn("嵌套解析失败,使用原始CSS:",error)}}const rootRule=generateRootRule(globalVariables,config);let finalCSS=processedCSS;if(selectorVariables.size>0){finalCSS=injectSelectorVariables(processedCSS,selectorVariables,config)}finalCSS=replaceVariableUses(finalCSS,globalVariables,selectorVariables,config);return rootRule+finalCSS}function autoProcessStyleTags(customConfig={}){const config={...defaultConfig,...customConfig};const styleTags=document.querySelectorAll(`style[${config.styleTagAttribute||"e"}]`);styleTags.forEach(styleTag=>{const originalCSS=styleTag.textContent;const convertedCSS=convert(originalCSS,config);const newStyleTag=document.createElement("style");newStyleTag.textContent=convertedCSS;styleTag.parentNode.insertBefore(newStyleTag,styleTag.nextSibling);if(!config.preserveOriginal){styleTag.remove()}else{styleTag.style.display="none"}});return styleTags.length}function config(config={}){defaultConfig={...defaultConfig,...config}}function apply(cssText,customConfig={}){const config={...defaultConfig,...customConfig};if(cssText){const converted=convert(cssText,config);const styleEl=document.createElement("style");styleEl.textContent=converted;document.head.appendChild(styleEl);return styleEl}else{if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",()=>{autoProcessStyleTags(config)})}else{autoProcessStyleTags(config)}}}const api={convert:convert,apply:apply,config:config,version:"1.8.0",supportsP3:detectP3Support(),detectP3Support:detectP3Support,colorUtils:{labToRGB:preciseLabToRGB,lchToLab:lchToLab,lchToRGB:function(L,C,H){const lab=lchToLab(L,C,H);return preciseLabToRGB(lab.L,lab.a,lab.b)},labToP3:labToP3,lchToP3:function(L,C,H){const lab=lchToLab(L,C,H);return labToP3(lab.L,lab.a,lab.b)},parseHexLab:function(hexString){const match=hexString.match(/lab#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i);if(!match)return null;const L_hex=match[1];const A_hex=match[2];const B_hex=match[3];const L=parseInt(L_hex,16)/255*100;const A=(parseInt(A_hex,16)-128)*1.5;const B=(parseInt(B_hex,16)-128)*1.5;return preciseLabToRGB(L,A,B)},parseHexLch:function(hexString){const match=hexString.match(/lch#([0-9a-f]{2})([0-9a-f]{2})(\d{1,3})/i);if(!match)return null;const L_hex=match[1];const C_hex=match[2];const H_dec=match[3];const L=parseInt(L_hex,16)/255*100;const C=parseInt(C_hex,16)/255*150;const H=parseInt(H_dec)/100*360;const lab=lchToLab(L,C,H);return preciseLabToRGB(lab.L,lab.a,lab.b)},generateColor:function(L,a,b,alpha=null,useP3=true){return generateColorString(L,a,b,{enableP3:useP3},alpha)},parseColor:function(colorString){try{const labMatch=colorString.match(/lab\(\s*([\d.]+)(%?)\s+([\d.-]+)\s+([\d.-]+)(?:\s*\/\s*([\d.%]+))?\s*\)/i);if(labMatch){let L=parseFloat(labMatch[1]);const A=parseFloat(labMatch[3]);const B=parseFloat(labMatch[4]);const alpha=labMatch[5]?labMatch[5].includes("%")?parseFloat(labMatch[5])/100:parseFloat(labMatch[5]):null;const colorStr=generateColorString(L,A,B,defaultConfig,alpha);return{L:L,A:A,B:B,alpha:alpha,rgb:preciseLabToRGB(L,A,B),p3:labToP3(L,A,B),colorString:colorStr}}const lchMatch=colorString.match(/lch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)(deg)?(?:\s*\/\s*([\d.%]+))?\s*\)/i);if(lchMatch){let L=parseFloat(lchMatch[1]);const C=parseFloat(lchMatch[3]);let H=parseFloat(lchMatch[4]);const alpha=lchMatch[6]?lchMatch[6].includes("%")?parseFloat(lchMatch[6])/100:parseFloat(lchMatch[6]):null;const lab=lchToLab(L,C,H);const colorStr=generateColorString(lab.L,lab.a,lab.b,defaultConfig,alpha);return{L:L,C:C,H:H,alpha:alpha,lab:lab,rgb:preciseLabToRGB(lab.L,lab.a,lab.b),p3:labToP3(lab.L,lab.a,lab.b),colorString:colorStr}}return null}catch(error){console.warn("无法解析颜色:",colorString,error);return null}}}};if(typeof window!=="undefined"){apply();Object.defineProperty(window.HTMLElement.prototype,"cssVar",{get(){const element=this;return new Proxy({},{get(target,prop){const varName=prop.startsWith("--")?prop:`--${prop}`;return element.style.getPropertyValue(varName)},set(target,prop,value){const varName=prop.startsWith("--")?prop:`--${prop}`;element.style.setProperty(varName,value);return true}})}})}return api}();if(typeof module!=="undefined"&&module.exports){module.exports=styimat}else{window.styimat=styimat}
|