Skip to content

Commit

Permalink
Trying stylus
Browse files Browse the repository at this point in the history
  • Loading branch information
PRO-2684 committed Sep 25, 2024
1 parent 514add3 commit a75a2d0
Show file tree
Hide file tree
Showing 9 changed files with 464 additions and 50 deletions.
130 changes: 130 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
16 changes: 1 addition & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,7 @@

### CI 版

若想体验最新的 CI 功能,可以下载源码后同上安装。(仅需下载下面列出的文件)

完成后的目录结构应该如下:

```
plugins (所有的插件目录)
└── transitio (此插件目录)
├── manifest.json (插件元数据)
├── main.js (插件代码)
├── preload.js (插件代码)
├── renderer.js (插件代码)
├── settings.html (插件设置界面)
├── icons/ (插件用到的图标)
└── modules/ (模块化的插件代码)
```
若想体验最新的 CI 功能,需要下载源码后安装要求的 NPM 依赖 (`npm install`)。

## 🤔 使用方法

Expand Down
16 changes: 10 additions & 6 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ const path = require("path");
const { BrowserWindow, ipcMain, webContents, shell } = require("electron");
const { extractUserStyleMetadata } = require("./modules/main/parser");
const { listCSS } = require("./modules/main/walker");
const { normalize, debounce, simpleLog, dummyLog } = require("./modules/main/utils");
const { normalize, debounce, simpleLog, dummyLog, renderStylus } = require("./modules/main/utils");

const isDebug = process.argv.includes("--transitio-debug");
const updateInterval = 1000;
const log = isDebug ? simpleLog : dummyLog;
let devMode = false;
let watcher = null;

const supportedPreprocessors = ["transitio", "stylus"];
const dataPath = LiteLoader.plugins.transitio.path.data;
const stylePath = path.join(dataPath, "styles");
const debouncedSet = debounce(LiteLoader.api.config.set, updateInterval);
Expand Down Expand Up @@ -100,7 +101,7 @@ function getStyle(absPath) {
}

// Send updated style to renderer
function updateStyle(absPath, webContent) {
async function updateStyle(absPath, webContent) {
absPath = normalize(absPath);
log("updateStyle", absPath);
const css = getStyle(absPath);
Expand All @@ -119,21 +120,24 @@ function updateStyle(absPath, webContent) {
meta.name ??= path.basename(absPath, ".css");
meta.description ??= "此文件没有描述";
meta.preprocessor ??= "transitio";
if (meta.preprocessor !== "transitio") {
log(`Unsupported preprocessor "${meta.preprocessor}" at ${absPath}`)
if (!supportedPreprocessors.includes(meta.preprocessor)) {
log(`Unsupported preprocessor "${meta.preprocessor}" at ${absPath}`);
return;
}
// Read variables config, delete non-existent ones
const udfVariables = config.styles[absPath].variables;
for (const [varName, varValue] of Object.entries(udfVariables)) {
if (varName in meta.variables) {
meta.variables[varName].value = varValue;
if (varName in meta.vars) {
meta.vars[varName].value = varValue;
} else {
log(`Variable "${varName}" not found in ${absPath}`);
delete config.styles[absPath].variables[varName];
updateConfig();
}
}
if (meta.preprocessor === "stylus") {
css = await renderStylus(absPath, css, meta.vars);
}
// Send message to renderer
const msg = { path: absPath, enabled, css, meta };
if (webContent) {
Expand Down
44 changes: 27 additions & 17 deletions modules/main/parser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Description: Transitio's parser module for UserStyle metadata extraction.
const usercssMeta = require("usercss-meta");

/**
* Get the description from the first line of the CSS content. (will be deprecated)
Expand Down Expand Up @@ -56,30 +57,39 @@ function processVar(value) {
* @returns {Object} The UserStyle metadata.
*/
function extractUserStyleMetadata(css) {
const result = { variables: {} };
const result = { vars: {} };
// Regular expression to match the UserStyle block with flexibility for multiple "=" and spaces
const userStyleRegex = /\/\*\s*=+\s*UserStyle\s*=+\s*([\s\S]*?)\s*=+\s*\/UserStyle\s*=+\s*\*\//;
const match = css.match(userStyleRegex);
if (match) { // If the UserStyle block is found
// Detect if preprocessor is `transitio`
const content = match[1]; // Extract the content within the UserStyle block
const lines = content.split('\n'); // Split the content by newline
lines.forEach(line => {
// Regular expression to match "@name value" pattern
const matchLine = line.trim().match(/^@(\S+)\s+(.+)$/);
if (matchLine) {
const name = matchLine[1]; // Extract the name
const value = matchLine[2]; // Extract the value
if (name === "var") {
const varData = processVar(value);
if (varData) {
const [varName, varObj] = varData;
result.variables[varName] = varObj;
const isTransitio = content.match(/@preprocessor\s+transitio\s*$/m);
if (!isTransitio) {
return usercssMeta.parse(match[0], {
mandatoryKeys: ["name"],
// unknownKey: "assign"
}).metadata;
} else {
const lines = content.split('\n'); // Split the content by newline
lines.forEach(line => {
// Regular expression to match "@name value" pattern
const matchLine = line.trim().match(/^@(\S+)\s+(.+)$/);
if (matchLine) {
const name = matchLine[1]; // Extract the name
const value = matchLine[2]; // Extract the value
if (name === "var") {
const varData = processVar(value);
if (varData) {
const [varName, varObj] = varData;
result.vars[varName] = varObj;
}
} else {
result[name] = value; // Store in the result object
}
} else {
result[name] = value; // Store in the result object
}
}
});
});
}
} else { // Fall back to the old method
const comment = getDesc(css) || "";
result["description"] = comment;
Expand Down
33 changes: 31 additions & 2 deletions modules/main/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Description: Some utility functions for main.
const stylus = require('stylus');

/**
* Normalize a path to Unix style.
Expand Down Expand Up @@ -34,6 +35,34 @@ function simpleLog(...args) {
* Logs nothing.
* @param {...any} args The arguments to log.
*/
function dummyLog(...args) {}
function dummyLog(...args) { }
/**
* Async wrapper for Stylus render.
* @param {string} path Path of the Stylus file.
* @param {string} content Content of the Stylus file.
* @param {Object} vars Variables to apply.
*/
async function renderStylus(path, content, vars) {
const varDef = Object.keys(vars).map(key => {
const variable = vars[key];
let value = variable.value;
if (variable.type === "select") {
// Map from option name to value
value = variable.options.find(opt => opt.name === value)?.value;
}
return `${key} = ${value}${variable.units ?? ""};\n`;
}).join("");
return new Promise((resolve, reject) => {
stylus(varDef + content)
.set("filename", path)
.render((err, css) => {
if (err) {
reject(err);
} else {
resolve(css);
}
});
});
}

module.exports = { normalize, debounce, simpleLog, dummyLog };
module.exports = { normalize, debounce, simpleLog, dummyLog, renderStylus };
5 changes: 2 additions & 3 deletions modules/renderer/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function constructVarValue(varObj) {
}
}
/**
* Apply variables to the CSS.
* Apply variables to the CSS (transitio preprocessor).
* @param {String} css CSS content.
* @param {Object} variables A dictionary of variables.
* @returns {String} The CSS content with variables applied.
Expand Down Expand Up @@ -89,8 +89,7 @@ function injectCSS(path, css) {
*/
function cssHelper(path, css, enabled, meta) {
const current = document.querySelector(`style[${styleDataAttr}="${path}"]`);
log("Applying variables to", path, meta.variables)
const processedCSS = enabled ? applyVariables(css, meta.variables) : `/* ${meta.description || "此文件没有描述"} */`;
const processedCSS = enabled ? (meta.preprocessor === "transitio" ? applyVariables(css, meta.vars) : css) : `/* ${meta.description || "此文件没有描述"} */`;
if (current) {
current.textContent = processedCSS;
} else {
Expand Down
Loading

0 comments on commit a75a2d0

Please sign in to comment.