From 1ceea081cc92d4208ec23d173b38fc70980d20a0 Mon Sep 17 00:00:00 2001 From: cipchk Date: Wed, 13 Nov 2024 01:16:36 +0800 Subject: [PATCH 1/2] feat: support ignore code - close #69, #61 --- .cssrem | 4 ++-- README.md | 12 ++++++++++++ README.zh-CN.md | 12 ++++++++++++ examples/.cssrem | 12 ++++++++++++ examples/demo.less | 13 +++++++++++-- src/completion.ts | 2 ++ src/hover.ts | 6 +++--- src/ignore-comment.ts | 13 +++++++++++++ src/line-annotation.ts | 2 ++ src/process.ts | 33 +++++++++++++++++++++------------ 10 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 examples/.cssrem create mode 100644 src/ignore-comment.ts diff --git a/.cssrem b/.cssrem index 498b1c1..fbd2d31 100644 --- a/.cssrem +++ b/.cssrem @@ -4,8 +4,8 @@ "fixedDigits": 3, "vw": true, "ignores": [ - "**/*.less", - "*.tsx" + // "**/*.less", + // "*.tsx" ], "ignoresViaCommand": [] } \ No newline at end of file diff --git a/README.md b/README.md index 9ea274b..0fde8ce 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,18 @@ Converts between `px` and `rem` units in VSCode, And support WXSS. + Move the cursor to `14px`, press `Alt + z` to convert `rem` + CLI: Press `F1`, enter `cssrem` +## Ignoring code + +You can ignore: +- Entire files by setting ignores in `.cssrem` or `.vscode/settings.json` +- The next line by using `// cssrem-disable-next-line` + +```less +// cssrem-disable-next-line +@media (min-width: 768px) {} +``` +> The above code will ignore processing of `768px` + # Support Language html vue css less scss sass stylus tpl(php smarty3) tsx jsx diff --git a/README.zh-CN.md b/README.zh-CN.md index 80cd1be..dd7972a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -25,6 +25,18 @@ + 光标至 `14px` 上,按下 `Alt + z` 对应转化 `rem` + 通过 `F1` 面板查找:`cssrem` +## 忽略代码 + +你可以忽略: +- 通过 `.cssrem` 或 `.vscode/settings.json` 设置 `ignores` 忽略整个文件 +- 通过使用 `// cssrem-disable-next-line` 表示忽略下一行的处理 + +```less +// cssrem-disable-next-line +@media (min-width: 768px) {} +``` +> 以上代码将忽略 `768px` 的处理 + # 支持语言 html vue css less scss sass stylus tpl(php smarty3) tsx jsx diff --git a/examples/.cssrem b/examples/.cssrem new file mode 100644 index 0000000..7e60e9c --- /dev/null +++ b/examples/.cssrem @@ -0,0 +1,12 @@ +{ + "$schema": "https://raw.githubusercontent.com/cipchk/vscode-cssrem/master/schema.json", + "rootFontSize": 24, + "fixedDigits": 3, + "vw": true, + "currentLine": "show", + "ignores": [ + // "**/*.less", + // "*.tsx" + ], + "ignoresViaCommand": [] +} diff --git a/examples/demo.less b/examples/demo.less index 22cd044..f3a4740 100644 --- a/examples/demo.less +++ b/examples/demo.less @@ -1,5 +1,14 @@ body { - font-size: 1rem; - padding: 10px 12px 1rem 1.2rem; + font-size: 48px; + padding: 10px 12px 24px 28.8px; margin: 7.5px 1vw; } + +// cssrem-disable-next-line +@media (min-width: 768px) { + body { + font-size: 28.8px; + padding: 10px 12px 24px 28.8px; + margin: 7.5px 1vw; + } +} diff --git a/src/completion.ts b/src/completion.ts index bb9f222..33bda53 100644 --- a/src/completion.ts +++ b/src/completion.ts @@ -1,6 +1,7 @@ import { CompletionItem, CompletionItemKind, CompletionItemProvider, MarkdownString, Position, Range, TextDocument } from 'vscode'; import { cog, isIngore } from './config'; import { CssRemProcess } from './process'; +import { isDisabledNextLine } from './ignore-comment'; export default class implements CompletionItemProvider { constructor(private lan: string, private process: CssRemProcess) {} @@ -9,6 +10,7 @@ export default class implements CompletionItemProvider { if (isIngore(document.uri)) return Promise.resolve([]); return new Promise(resolve => { + if (isDisabledNextLine(document, position.line)) return null; const lineText = document.getText(new Range(position.with(undefined, 0), position)); const res = this.process.convert(lineText); if (res == null || res.length === 0) { diff --git a/src/hover.ts b/src/hover.ts index 2c9b77d..efdae5d 100644 --- a/src/hover.ts +++ b/src/hover.ts @@ -1,6 +1,7 @@ import { Hover, HoverProvider, MarkdownString, Position, ProviderResult, TextDocument } from 'vscode'; import { cog, isIngore } from './config'; import { RULES } from './rules'; +import { isDisabledNextLine } from './ignore-comment'; export default class implements HoverProvider { private getText(line: string, pos: Position): string { @@ -21,9 +22,8 @@ export default class implements HoverProvider { if (isIngore(doc.uri)) return null; const line = doc.lineAt(pos.line).text.trim(); const text = this.getText(line, pos); - if (!text) { - return null; - } + if (!text) return null; + if (isDisabledNextLine(doc, pos.line)) return null; let results = RULES.filter(w => w.hover && w.hover.test(text)) .map(rule => rule.hoverFn(text)) .filter(h => h != null && h.documentation); diff --git a/src/ignore-comment.ts b/src/ignore-comment.ts new file mode 100644 index 0000000..6366974 --- /dev/null +++ b/src/ignore-comment.ts @@ -0,0 +1,13 @@ +import { TextDocument } from 'vscode'; + +export const DISABLE_NEXT_LINE_COMMAND = 'cssrem-disable-next-line'; + +export function isDisabledNextLineViaText(line: string): boolean { + return line.includes(DISABLE_NEXT_LINE_COMMAND); +} + +export function isDisabledNextLine(doc: TextDocument, lineNumber: number): boolean { + if (lineNumber - 1 < 0) return false; + const line = doc.lineAt(lineNumber - 1).text.trim(); + return isDisabledNextLineViaText(line); +} diff --git a/src/line-annotation.ts b/src/line-annotation.ts index 0d37a38..463e6e2 100644 --- a/src/line-annotation.ts +++ b/src/line-annotation.ts @@ -13,6 +13,7 @@ import { import { cog, isIngore } from './config'; import { HoverResult } from './interface'; import { RULES } from './rules'; +import { isDisabledNextLine } from './ignore-comment'; const annotationDecoration = window.createTextEditorDecorationType({ after: { @@ -93,6 +94,7 @@ export class LineAnnotation implements Disposable { private genMessage(doc: TextDocument, lineNumber: number): string | null { const text = doc.lineAt(lineNumber).text.trim(); if (text.length <= 0) return null; + if (isDisabledNextLine(doc, lineNumber)) return null; const values = text.match(/([.0-9]+(px|rem|rpx|vw))/g); if (values == null) return null; diff --git a/src/process.ts b/src/process.ts index aedf08e..2d3043f 100644 --- a/src/process.ts +++ b/src/process.ts @@ -2,9 +2,10 @@ import { ConvertResult, Rule, RuleOPType, Type } from './interface'; import { RULES } from './rules'; import { Position, Range, Selection, TextEditor } from 'vscode'; import { isIngore } from './config'; +import { isDisabledNextLine, isDisabledNextLineViaText } from './ignore-comment'; export class CssRemProcess { - convert(text: string): ConvertResult[] | null { + convert(text?: string): ConvertResult[] | null { const res = this.getRule('single', text); if (res.length === 0) { return null; @@ -13,23 +14,31 @@ export class CssRemProcess { return res.map(i => i.rule.fn(i.text)); } - convertAll(code: string, ignores: string[], type: Type): string { + private convertAll(code: string, ignores: string[], type: Type): string { if (!code) { return code; } const rule = RULES.find(w => w.type === type); - return code.replace(rule.all, (word: string) => { - if (ignores.includes(word)) { - return word; - } - const res = rule.fn(word); - if (res) { - return res.value; - } - return word; - }); + const lines = code.split('\n'); + + const result = lines + .map((line, lineIndex) => { + return line.replace(rule.all, word => { + if (ignores.includes(word)) { + return word; + } + if (lineIndex > 0 && isDisabledNextLineViaText(lines[lineIndex - 1])) return null; + const res = rule.fn(word); + if (res) { + return res.value; + } + return word; + }); + }) + .join('\n'); + return result; } private getRule(type: RuleOPType, text: string): { rule: Rule; text: string }[] { From f422f8aa0dcf34a6f9d5ab4da584158d6ac48cb7 Mon Sep 17 00:00:00 2001 From: cipchk Date: Wed, 13 Nov 2024 03:15:17 +0800 Subject: [PATCH 2/2] chore: fix --- src/process.ts | 60 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/process.ts b/src/process.ts index 021aea1..3ebd015 100644 --- a/src/process.ts +++ b/src/process.ts @@ -1,17 +1,17 @@ -import { ConvertResult, Rule, RuleOPType, Type } from './interface'; -import { RULES } from './rules'; -import { Position, Range, Selection, TextEditor } from 'vscode'; -import { isIngore } from './config'; -import { isDisabledNextLine, isDisabledNextLineViaText } from './ignore-comment'; +import { ConvertResult, Rule, RuleOPType, Type } from "./interface"; +import { RULES } from "./rules"; +import { Position, Range, Selection, TextEditor } from "vscode"; +import { isIngore } from "./config"; +import { isDisabledNextLineViaText } from "./ignore-comment"; export class CssRemProcess { - convert(text?: string): ConvertResult[] | null { - const res = this.getRule('single', text); + convert(text: string): ConvertResult[] | null { + const res = this.getRule("single", text); if (res.length === 0) { return null; } - return res.map(i => i.rule.fn(i.text)!); + return res.map((i) => i.rule.fn(i.text)!); } private convertAll(code: string, ignores: string[], type: Type): string { @@ -19,20 +19,22 @@ export class CssRemProcess { return code; } - const rule = RULES.find(w => w.type === type); + const rule = RULES.find((w) => w.type === type); if (!rule) { return code; } - const lines = code.split('\n'); + const lines = code.split("\n"); const result = lines .map((line, lineIndex) => { - return line.replace(rule.all, word => { + return line.replace(rule.all, (word) => { if (ignores.includes(word)) { return word; } - if (lineIndex > 0 && isDisabledNextLineViaText(lines[lineIndex - 1])) return null; + if (lineIndex > 0 && isDisabledNextLineViaText(lines[lineIndex - 1])) + return word; + const res = rule.fn(word); if (res) { return res.value; @@ -40,11 +42,14 @@ export class CssRemProcess { return word; }); }) - .join('\n'); + .join("\n"); return result; } - private getRule(type: RuleOPType, text: string): { rule: Rule; text: string }[] { + private getRule( + type: RuleOPType, + text: string + ): { rule: Rule; text: string }[] { const result: { rule: Rule; text: string }[] = []; for (const rule of RULES) { const match = text.match((rule as any)[type]); @@ -56,22 +61,29 @@ export class CssRemProcess { } private getWordRange(textEditor: TextEditor, type: Type): Range | null { - const position = new Position(textEditor.selection.start.line, textEditor.selection.start.character); + const position = new Position( + textEditor.selection.start.line, + textEditor.selection.start.character + ); const range = textEditor.document.getWordRangeAtPosition(position); if (!range) return null; const word = textEditor.document.getText(range); if (!word) return null; - const rule = RULES.find(w => w.type === type); + const rule = RULES.find((w) => w.type === type); return rule && rule.all.test(word) ? range : null; } - modifyDocument(textEditor: TextEditor, ignoresViaCommand: string[], type: Type): void { + modifyDocument( + textEditor: TextEditor, + ignoresViaCommand: string[], + type: Type + ): void { const doc = textEditor.document; if (isIngore(doc.uri)) return; let selection: Selection | Range = textEditor.selection; // When the cursor is in the valid range in switch mode - if (selection.isEmpty && type.toLowerCase().includes('switch')) { + if (selection.isEmpty && type.toLowerCase().includes("switch")) { const wordRange = this.getWordRange(textEditor, type); if (wordRange) { selection = wordRange; @@ -79,13 +91,19 @@ export class CssRemProcess { } if (selection.isEmpty) { const start = new Position(0, 0); - const end = new Position(doc.lineCount - 1, doc.lineAt(doc.lineCount - 1).text.length); + const end = new Position( + doc.lineCount - 1, + doc.lineAt(doc.lineCount - 1).text.length + ); selection = new Range(start, end); } const text = doc.getText(selection); - textEditor.edit(builder => { - builder.replace(selection, this.convertAll(text, ignoresViaCommand, type)); + textEditor.edit((builder) => { + builder.replace( + selection, + this.convertAll(text, ignoresViaCommand, type) + ); }); } }