├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── images ├── dark_flex │ ├── content_center.svg │ ├── content_center_column.svg │ ├── content_flex-end.svg │ ├── content_flex-end_column.svg │ ├── content_flex-start.svg │ ├── content_flex-start_column.svg │ ├── content_space-around.svg │ ├── content_space-around_column.svg │ ├── content_space-between.svg │ ├── content_space-between_column.svg │ ├── content_space-evenly.svg │ ├── content_space-evenly_column.svg │ ├── content_stretch.svg │ ├── content_stretch_column.svg │ ├── icon_flex_direction_column.svg │ ├── icon_flex_direction_column_reverse.svg │ ├── icon_flex_direction_row.svg │ ├── icon_flex_direction_row_reverse.svg │ ├── items_baseline.svg │ ├── items_center.svg │ ├── items_center_column.svg │ ├── items_flex-end.svg │ ├── items_flex-end_column.svg │ ├── items_flex-start.svg │ ├── items_flex-start_column.svg │ ├── items_stretch.svg │ ├── items_stretch_column.svg │ ├── justify-items-center.svg │ ├── justify-items-end.svg │ ├── justify-items-start.svg │ ├── justify-items-stretch.svg │ ├── wrap_nowrap.svg │ ├── wrap_nowrap_column.svg │ ├── wrap_wrap.svg │ └── wrap_wrap_column.svg ├── flex_dark.svg ├── flex_light.svg ├── light_flex │ ├── content_center.svg │ ├── content_center_column.svg │ ├── content_flex-end.svg │ ├── content_flex-end_column.svg │ ├── content_flex-start.svg │ ├── content_flex-start_column.svg │ ├── content_space-around.svg │ ├── content_space-around_column.svg │ ├── content_space-between.svg │ ├── content_space-between_column.svg │ ├── content_space-evenly.svg │ ├── content_space-evenly_column.svg │ ├── content_stretch.svg │ ├── content_stretch_column.svg │ ├── icon_flex_direction_column.svg │ ├── icon_flex_direction_column_reverse.svg │ ├── icon_flex_direction_row.svg │ ├── icon_flex_direction_row_reverse.svg │ ├── items_baseline.svg │ ├── items_center.svg │ ├── items_center_column.svg │ ├── items_flex-end.svg │ ├── items_flex-end_column.svg │ ├── items_flex-start.svg │ ├── items_flex-start_column.svg │ ├── items_stretch.svg │ ├── items_stretch_column.svg │ ├── justify-items-center.svg │ ├── justify-items-end.svg │ ├── justify-items-start.svg │ ├── justify-items-stretch.svg │ ├── wrap_nowrap.svg │ ├── wrap_nowrap_column.svg │ ├── wrap_wrap.svg │ └── wrap_wrap_column.svg ├── logo.png └── readme │ └── demo.gif ├── package-lock.json ├── package.json ├── src ├── extension.ts └── flexboxPatterns.ts ├── test └── text.scss └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .vscode-test/ 4 | *.vsix 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [{ 8 | "name": "Run Extension", 9 | "type": "extensionHost", 10 | "request": "launch", 11 | "runtimeExecutable": "${execPath}", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/out/**/*.js" 17 | ], 18 | "preLaunchTask": "npm: watch" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "out": false 4 | }, 5 | "search.exclude": { 6 | "out": true 7 | }, 8 | "typescript.tsc.autoDetect": "off" 9 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 QiuQiu_XT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS FlexCode(Grid) 2 | > 欢迎反馈交流,[点个Star~](https://github.com/xutao-o/css-flex-code) 3 | > Welcome to provide feedback and communicate, [please give it a star~](https://github.com/xutao-o/css-flex-code) 4 | 5 | [VS Code市场安装地址](https://marketplace.visualstudio.com/items?itemName=qiuqiu-xt.css-flex) 6 | [VS Code market installation address](https://marketplace.visualstudio.com/items?itemName=qiuqiu-xt.css-flex) 7 | 8 | 快捷生成CSS Flex布局与Grid布局代码的VS Code插件(类似于Google开发者控制台里的Flex布局工具) 9 | A VS Code extension that quickly generates CSS Flex and Grid layout code. 10 | 11 | - 支持多类css文件与框架(Support for multiple CSS files and frameworks) 12 | - 保持代码缩进格式(Maintain code indentation format) 13 | - 兼容深色与浅色主题(Compatible with both dark and light themes) 14 | - 自动替换同属性代码(Automatically replaces duplicate code with the same properties) 15 | 16 | ## 💻示例(Demo) 17 | ![CSS Flex示例](https://resource-wangsu.helplook.net/docker_production/kn8ndd/article/4FZxPK/67da69e407ee7.gif) 18 | 19 | ### ⚠️注意事项(Warning ) 20 | 不建议在压缩后的CSS代码或HTML的行内样式中使用插件 21 | This plugin is not recommended for use with compressed CSS code or inline styles in HTML. 22 | 23 | ### 😉致谢(Thank) 24 | - 由[小秋AI](https://www.xqai.net/)提供辅助支持,赞美AI!( [XiaoQiu AI](https://www.xqai.net/) provides auxiliary support. Praising AI!) -------------------------------------------------------------------------------- /images/dark_flex/content_center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_center_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_flex-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_flex-end_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_flex-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_flex-start_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-around.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-around_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-between.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-between_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-evenly.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_space-evenly_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/content_stretch_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/icon_flex_direction_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/icon_flex_direction_column_reverse.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/icon_flex_direction_row.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/icon_flex_direction_row_reverse.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_baseline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_center_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_flex-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_flex-end_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_flex-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_flex-start_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/items_stretch_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/justify-items-center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/justify-items-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/justify-items-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/justify-items-stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/wrap_nowrap.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/wrap_nowrap_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/wrap_wrap.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/dark_flex/wrap_wrap_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/flex_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/flex_light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/light_flex/content_center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_center_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_flex-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_flex-end_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_flex-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_flex-start_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-around.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-around_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-between.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-between_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-evenly.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_space-evenly_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/content_stretch_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/icon_flex_direction_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/icon_flex_direction_column_reverse.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/icon_flex_direction_row.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/icon_flex_direction_row_reverse.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_baseline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_center_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_flex-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_flex-end_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_flex-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_flex-start_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/items_stretch_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/justify-items-center.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/justify-items-end.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/justify-items-start.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/justify-items-stretch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/wrap_nowrap.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/wrap_nowrap_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/wrap_wrap.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/light_flex/wrap_wrap_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xutao-o/css-flex-code/d9226bd77d4dddc020a89fc2590cd7f597cab2dc/images/logo.png -------------------------------------------------------------------------------- /images/readme/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xutao-o/css-flex-code/d9226bd77d4dddc020a89fc2590cd7f597cab2dc/images/readme/demo.gif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css_flex_code", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "css_flex_code", 9 | "version": "0.0.1", 10 | "devDependencies": { 11 | "@types/node": "^16.18.34", 12 | "@types/vscode": "^1.73.0", 13 | "typescript": "^5.2.2" 14 | }, 15 | "engines": { 16 | "vscode": "^1.75.0" 17 | } 18 | }, 19 | "node_modules/@types/node": { 20 | "version": "16.18.34", 21 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", 22 | "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==", 23 | "dev": true 24 | }, 25 | "node_modules/@types/vscode": { 26 | "version": "1.73.1", 27 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.73.1.tgz", 28 | "integrity": "sha512-eArfOrAoZVV+Ao9zQOCaFNaeXj4kTCD+bGS2gyNgIFZH9xVMuLMlRrEkhb22NyxycFWKV1UyTh03vhaVHmqVMg==", 29 | "dev": true 30 | }, 31 | "node_modules/typescript": { 32 | "version": "5.2.2", 33 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 34 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 35 | "dev": true, 36 | "bin": { 37 | "tsc": "bin/tsc", 38 | "tsserver": "bin/tsserver" 39 | }, 40 | "engines": { 41 | "node": ">=14.17" 42 | } 43 | } 44 | }, 45 | "dependencies": { 46 | "@types/node": { 47 | "version": "16.18.34", 48 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", 49 | "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==", 50 | "dev": true 51 | }, 52 | "@types/vscode": { 53 | "version": "1.73.1", 54 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.73.1.tgz", 55 | "integrity": "sha512-eArfOrAoZVV+Ao9zQOCaFNaeXj4kTCD+bGS2gyNgIFZH9xVMuLMlRrEkhb22NyxycFWKV1UyTh03vhaVHmqVMg==", 56 | "dev": true 57 | }, 58 | "typescript": { 59 | "version": "5.2.2", 60 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 61 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 62 | "dev": true 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-flex", 3 | "displayName": "CSS FlexCode(Grid)", 4 | "description": "一键生成Flex布局/Grid布局的CSS代码插件(类似于Google开发者控制台里的Flex布局工具) | A plugin to generate CSS Flex layout code (Similar to the Flexbox inspector tool in Google Developer Console)", 5 | "version": "1.1.1", 6 | "publisher": "qiuqiu-xt", 7 | "repository": "https://github.com/xutao-o/css-flex-code", 8 | "icon": "images/logo.png", 9 | "engines": { 10 | "vscode": "^1.75.0" 11 | }, 12 | "categories": [ 13 | "Snippets" 14 | ], 15 | "activationEvents": [ 16 | "onLanguage:css", 17 | "onLanguage:less", 18 | "onLanguage:sass", 19 | "onLanguage:scss", 20 | "onLanguage:vue", 21 | "onLanguage:html", 22 | "onLanguage:jsx", 23 | "onLanguage:tsx", 24 | "onLanguage:svelte", 25 | "onLanguage:astro", 26 | "onLanguage:styl", 27 | "onLanguage:htm" 28 | ], 29 | "main": "./out/extension.js", 30 | "contributes": { 31 | "languages": [ 32 | ] 33 | }, 34 | "scripts": { 35 | "vscode:prepublish": "npm run compile", 36 | "compile": "tsc -p ./", 37 | "watch": "tsc -watch -p ./" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "^16.18.34", 41 | "@types/vscode": "^1.73.0", 42 | "typescript": "^5.2.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { join } from 'path'; 3 | import * as flexboxPatterns from './flexboxPatterns'; 4 | 5 | const supportedFiles = ['css', 'less', 'sass', 'scss', 'vue', 'html']; 6 | let decorationType: vscode.TextEditorDecorationType; 7 | 8 | export function activate(context: vscode.ExtensionContext) { 9 | decorationType = vscode.window.createTextEditorDecorationType({ 10 | after: { 11 | margin: '0 0 0 0.25rem', 12 | width: '0.9rem', 13 | }, 14 | dark: { 15 | after: { 16 | contentIconPath: context.asAbsolutePath( 17 | '/images/flex_light.svg' 18 | ) 19 | }, 20 | }, 21 | light: { 22 | after: { 23 | contentIconPath: context.asAbsolutePath( 24 | '/images/flex_dark.svg' 25 | ), 26 | }, 27 | }, 28 | }); 29 | 30 | const activeEditor = vscode.window.activeTextEditor; 31 | 32 | if (activeEditor) { 33 | decorate(activeEditor); 34 | } 35 | 36 | 37 | // 事件 38 | const disposableCommand = vscode.commands.registerCommand( 39 | 'flexcode.generating', 40 | (uri) => { 41 | const editor = vscode.window.activeTextEditor; 42 | if (!editor) { 43 | return; 44 | } 45 | const line = editor.document.lineAt(uri.posLine); 46 | // 根据缩进设置处理缩进格式 47 | let indentation = ''; 48 | const tabSize = editor.options.tabSize || 4; 49 | const insertSpaces = editor.options.insertSpaces; 50 | const indentationLength = line.firstNonWhitespaceCharacterIndex; 51 | if (insertSpaces) { 52 | indentation = ' '.repeat(indentationLength); 53 | } else { 54 | const tabsCount = Math.floor(indentationLength / Number(tabSize)); 55 | const spacesCount = indentationLength % Number(tabSize); 56 | indentation = '\t'.repeat(tabsCount) + ' '.repeat(spacesCount); 57 | } 58 | let upText = false 59 | // 遍历每个字符 60 | for (let i = uri.posLine - 1; i >= 0; i--) { 61 | const line = editor.document.lineAt(i); 62 | if(line.text.includes("{")){ 63 | break 64 | } 65 | if(line.text.includes(uri.attr + ":")){ 66 | upText = true 67 | editor.edit(editBuilder => { 68 | editBuilder.replace(line.range , indentation + `${uri.attr}: ${uri.code};`); 69 | }); 70 | break 71 | } 72 | } 73 | for (let i = uri.posLine + 1; i < editor.document.lineCount; i++) { 74 | const line = editor.document.lineAt(i); 75 | if(line.text.includes("{") || line.text.includes("}")){ 76 | break 77 | } 78 | if(line.text.includes(uri.attr + ":")){ 79 | upText = true 80 | editor.edit(editBuilder => { 81 | editBuilder.replace(line.range , indentation + `${uri.attr}: ${uri.code};`); 82 | }); 83 | break 84 | } 85 | } 86 | if(!upText){ 87 | // 插入布局样式 88 | editor.edit(editBuilder => { 89 | const insertPosition = new vscode.Position(line.lineNumber, line.range.end.character); 90 | editBuilder.insert(insertPosition, '\n'+ indentation + `${uri.attr}: ${uri.code};`); 91 | }); 92 | } 93 | } 94 | ); 95 | 96 | const disposableVisibleTextEditors = vscode.window.onDidChangeVisibleTextEditors((event) => { 97 | let editor = vscode.window.activeTextEditor; 98 | 99 | if (editor && supportedFiles.includes(editor.document.languageId)) { 100 | decorate(editor); 101 | } 102 | }); 103 | 104 | const disposableChangeDocument = vscode.workspace.onDidChangeTextDocument( 105 | (event) => { 106 | const openEditor = vscode.window.visibleTextEditors.filter( 107 | (editor) => editor.document.uri === event.document.uri 108 | )[0]; 109 | 110 | if ( 111 | openEditor && 112 | supportedFiles.includes(openEditor.document.languageId) 113 | ) { 114 | decorate(openEditor); 115 | } 116 | } 117 | ); 118 | 119 | // 悬浮信息 120 | const hoverProvider: vscode.HoverProvider = { 121 | provideHover(doc, pos, token): vscode.ProviderResult { 122 | const range = getPropertyRangeAtPosition(doc, pos); 123 | if (range === undefined) { 124 | return; 125 | } 126 | const markdownString = buildMarkdownString(context, pos.line); 127 | return new vscode.Hover(markdownString, range); 128 | }, 129 | }; 130 | 131 | const disposableHoverProvider = vscode.languages.registerHoverProvider( 132 | supportedFiles, 133 | hoverProvider 134 | ); 135 | 136 | context.subscriptions.push( 137 | disposableCommand, 138 | disposableHoverProvider, 139 | disposableChangeDocument, 140 | disposableVisibleTextEditors, 141 | ); 142 | } 143 | 144 | 145 | // 追加图标 146 | function decorate(editor: vscode.TextEditor) { 147 | const sourceCode = editor.document.getText(); 148 | 149 | let decorationsArray: vscode.DecorationOptions[] = []; 150 | 151 | const sourceCodeArr = sourceCode.split('\n'); 152 | 153 | 154 | function matchAll(pattern: RegExp, text: string): Array { 155 | const out: RegExpMatchArray[] = []; 156 | let match: RegExpMatchArray | null; 157 | 158 | pattern.lastIndex = 0; 159 | 160 | while ((match = pattern.exec(text))) { 161 | out.push(match); 162 | } 163 | 164 | return out; 165 | } 166 | 167 | for (let line = 0; line < sourceCodeArr.length; line++) { 168 | const sourceCode = sourceCodeArr[line]; 169 | 170 | let matches = [] as any; 171 | for (const pattern of flexboxPatterns.allFlexboxPatterns) { 172 | matches = matchAll(pattern, sourceCode); 173 | if (matches.length > 0) { 174 | break; 175 | } 176 | } 177 | if (matches.length > 0) { 178 | matches.forEach((match:any) => { 179 | if (match.index !== undefined) { 180 | const flexIndex = sourceCode.indexOf(';', match.index) + 1; 181 | let range = new vscode.Range( 182 | new vscode.Position(line, match.index), 183 | new vscode.Position(line, flexIndex) 184 | ); 185 | let decoration = { range }; 186 | decorationsArray.push(decoration); 187 | } 188 | }); 189 | } 190 | } 191 | editor.setDecorations(decorationType, decorationsArray); 192 | } 193 | 194 | 195 | // 主题 196 | function isDarkTheme() { 197 | const activeTheme = vscode.window.activeColorTheme; 198 | return activeTheme.kind === vscode.ColorThemeKind.Dark; 199 | } 200 | 201 | 202 | 203 | // 悬浮信息 204 | const getCommandUri = (attr:string, code:string, posLine: number) => { 205 | return vscode.Uri.parse(`command:flexcode.generating?${encodeURIComponent(JSON.stringify([{ attr, code, posLine }]))}`) 206 | } 207 | function buildMarkdownString( 208 | context: vscode.ExtensionContext, 209 | posLine: number 210 | ): vscode.MarkdownString[] { 211 | let markdownString: vscode.MarkdownString[] = []; 212 | const flexboxCommand = new vscode.MarkdownString(); 213 | let imgUrl = isDarkTheme() ? 'light_flex' : 'dark_flex' 214 | const editor = vscode.window.activeTextEditor as any; 215 | let direction = "row" 216 | 217 | let LineText = editor.document.lineAt(posLine).text 218 | let flexBol = LineText.includes('flex') 219 | // 遍历字符 220 | for (let i = posLine - 1; i >= 0; i--) { 221 | const line = editor.document.lineAt(i); 222 | if(line.text.includes("{")){ 223 | break 224 | } 225 | if(line.text.includes("flex-direction:")){ 226 | const result = line.text.match(/flex-direction:\s*(.*?);/); 227 | if (result && result.length > 1) { 228 | direction = result[1].trim(); 229 | } 230 | break 231 | } 232 | } 233 | for (let i = posLine + 1; i < editor.document.lineCount; i++) { 234 | const line = editor.document.lineAt(i); 235 | if(line.text.includes("{") || line.text.includes("}")){ 236 | break 237 | } 238 | if(line.text.includes("flex-direction:")){ 239 | const result = line.text.match(/flex-direction:\s*(.*?);/); 240 | if (result && result.length > 1) { 241 | direction = result[1].trim(); 242 | } 243 | break 244 | } 245 | } 246 | 247 | if(!['row','column','row-reverse','column-reverse'].includes(direction)){ 248 | direction = 'row' 249 | } 250 | let svgType = direction.includes('column') ? '_column' : '' 251 | 252 | const getSvg = (key: string) => { 253 | const alignmentMap = { 254 | 'flex-start': { 255 | 'row': 'content_flex-start_column.svg', 256 | 'column': 'content_flex-start.svg', 257 | 'row-reverse': 'content_flex-end_column.svg', 258 | 'column-reverse': 'content_flex-end.svg' 259 | }, 260 | 'flex-end': { 261 | 'row': 'content_flex-end_column.svg', 262 | 'column': 'content_flex-end.svg', 263 | 'row-reverse': 'content_flex-start_column.svg', 264 | 'column-reverse': 'content_flex-start.svg' 265 | } 266 | } as any; 267 | 268 | if (alignmentMap[key]) { 269 | return alignmentMap[key][direction]; 270 | } 271 | }; 272 | 273 | const flex_html = `flex-direction 274 |
275 | 276 | 277 |   278 | 279 | 280 |   281 | 282 | 283 |   284 | 285 | 286 | 287 |
288 | flex-wrap 289 |
290 | 291 | 292 |   293 | 294 | 295 | 296 |
297 | align-content 298 |
299 | 300 | 301 |   302 | 303 | 304 |   305 | 306 | 307 |   308 | 309 | 310 |   311 | 312 | 313 |   314 | 315 | 316 | 317 |
318 | justify-content 319 |
320 | 321 | 322 |   323 | 324 | 325 |   326 | 327 | 328 |   329 | 330 | 331 |   332 | 333 | 334 |   335 | 336 | 337 | 338 |
339 | align-items 340 |
341 | 342 | 343 |   344 | 345 | 346 |   347 | 348 | 349 |   350 | 351 | 352 |   353 | 354 | 355 | 356 |
` 357 | 358 | const grid_html = `align-content 359 |
360 | 361 | 362 |   363 | 364 | 365 |   366 | 367 | 368 |   369 | 370 | 371 |   372 | 373 | 374 | 375 |
376 | justify-content 377 |
378 | 379 | 380 |   381 | 382 | 383 |   384 | 385 | 386 |   387 | 388 | 389 |   390 | 391 | 392 |   393 | 394 | 395 | 396 |
397 | align-items 398 |
399 | 400 | 401 |   402 | 403 | 404 |   405 | 406 | 407 |   408 | 409 | 410 |   411 | 412 | 413 | 414 |
justify-items 415 |
416 | 417 | 418 |   419 | 420 | 421 |   422 | 423 | 424 |   425 | 426 | 427 |   428 |
` 429 | 430 | let HoverHtml = flexBol ? flex_html : grid_html 431 | flexboxCommand.appendMarkdown(HoverHtml) 432 | flexboxCommand.isTrusted = true 433 | flexboxCommand.supportHtml = true 434 | markdownString.push(flexboxCommand) 435 | return markdownString 436 | } 437 | 438 | function getPropertyRangeAtPosition( 439 | doc: vscode.TextDocument, 440 | pos: vscode.Position 441 | ) { 442 | let propertyRange: vscode.Range | undefined; 443 | 444 | for (const pattern of flexboxPatterns.allFlexboxPatterns) { 445 | const range = doc.getWordRangeAtPosition(pos, pattern); 446 | 447 | if (range) { 448 | propertyRange = range; 449 | 450 | break; 451 | } 452 | } 453 | 454 | return propertyRange; 455 | } 456 | 457 | export function deactivate() { } 458 | -------------------------------------------------------------------------------- /src/flexboxPatterns.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Matches `display: flex` property 3 | */ 4 | export const displayFlexPattern = /display:\s*flex;/g; 5 | 6 | /** 7 | * Matches `display: inline-flex` property 8 | */ 9 | export const displayInlineFlexPattern = /display:\s*inline-flex;/g; 10 | 11 | /** 12 | * Matches `display: grid` property 13 | */ 14 | export const displayGridPattern = /display:\s*grid;/g; 15 | 16 | /** 17 | * Matches `display: inline-grid` property 18 | */ 19 | export const displayInlineGridPattern = /display:\s*inline-grid;/g; 20 | 21 | export const allFlexboxPatterns = [ 22 | displayFlexPattern, 23 | displayInlineFlexPattern, 24 | displayGridPattern, 25 | displayInlineGridPattern 26 | ]; -------------------------------------------------------------------------------- /test/text.scss: -------------------------------------------------------------------------------- 1 | .test{ 2 | display: flex; 3 | display: grid; 4 | flex-direction: column-reverse; 5 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2020", 5 | "lib": ["es2020"], 6 | "outDir": "./out", 7 | "sourceMap": true, 8 | "strict": true, 9 | "rootDir": "src" 10 | }, 11 | "exclude": ["node_modules", ".vscode-test"] 12 | } --------------------------------------------------------------------------------