This commit is contained in:
microud 2020-01-03 00:15:54 +08:00
parent 786642fee7
commit d7dc4d826a
29 changed files with 705 additions and 23162 deletions

313
README.md
View File

@ -6,12 +6,9 @@
https://any86.github.io/any-rule/
## 🍭vscode插件
1. 安装vscode中插件搜索框输入**any-rule**
2. 安装完毕后按**F1**(或者ctrl+shift+p).
3. 输入"**zz**"可以看到正则列表.
4. 或者**输入关键词**, 比如"手机".
- 默认的触发字符串为 `zz`在JavaScript或者Typescript文件中输入 `zz.` 即可触发选择
![预览视频](https://user-images.githubusercontent.com/8264787/69204566-36b97800-0b82-11ea-8553-dfc06f709926.gif)
- 可以在设置中修改
## :fire:关于PR
欢迎大家PR, 步骤如下:
@ -22,309 +19,3 @@ https://any86.github.io/any-rule/
在此感谢大家对**any-rule**做出的贡献!
## 🍔正则
### 火车车次
```javascript
/^[GCDZTSPKXLY1-9]\d{1,4}$/
```
### 手机机身码(IMEI)
```javascript
/^\d{15,17}$/
```
### 必须带端口号的网址(或ip)
```javascript
/^(((ht|f)tps?):\/\/)?[\w\-]+(\.[\w\-]+)+:\d{0,5}\/?/
```
### 网址(支持端口和"?+参数"和"#+参数)
```javascript
/^(((ht|f)tps?):\/\/)?[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/
```
### 统一社会信用代码
```javascript
/^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/
```
### 迅雷链接
```javascript
/^thunderx?:\/\/[a-zA-Z\d]+=$/
```
### ed2k链接(宽松匹配)
```javascript
/^ed2k:\/\/\|file\|.+\|\/$/
```
### 磁力链接(宽松匹配)
```javascript
/^magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*$/
```
### 子网掩码
```javascript
/^(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/
```
### linux"文件夹"路径
```javascript
/^\/(\w+\/?)+$/
```
### linux"文件"路径
```javascript
/^\/(\w+\/)+\w+\.\w+$/
```
### window下"文件夹"路径
```javascript
/^[a-zA-Z]:\\(?:\w+\\?)*$/
```
### window下"文件"路径
```javascript
/^[a-zA-Z]:\\(?:\w+\\)*\w+\.\w+$/
```
### A股代码
```javascript
/^(s[hz]|S[HZ])(000[\d]{3}|002[\d]{3}|300[\d]{3}|600[\d]{3}|60[\d]{4})$/
```
### 大于等于0, 小于等于150, 支持小数位出现5, 如145.5, 用于判断考卷分数
```javascript
/^150$|^(?:\d|[1-9]\d|1[0-4]\d)(?:.5)?$/
```
### html注释
```javascript
/^<!--[\s\S]*?-->$/
```
### md5格式(32位)
```javascript
/^[a-f0-9]{32}$/
```
### 版本号格式必须为X.Y.Z
```javascript
/^\d+(?:\.\d+){2}$/
```
### 视频链接地址(视频格式可按需增删)
```javascript
/^https?:\/\/(.+\/)+.+(\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|mp4))$/i
```
### 图片链接地址(图片格式可按需增删)
```javascript
/^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i
```
### 24小时制时间HH:mm:ss
```javascript
/^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/
```
### 12小时制时间hh:mm:ss
```javascript
/^(?:1[0-2]|0?[1-9]):[0-5]\d:[0-5]\d$/
```
### base64格式
```javascript
/^\s*data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)?)?(?:;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i
```
### 数字/货币金额(支持负数、千分位分隔符)
```javascript
/(?:^[-]?[1-9]\d{0,2}(?:$|(?:,\d{3})*(?:$|(\.\d{1,2}$))))|(?:(?:^[0](\.\d{1,2})?)|(?:^[-][0]\.\d{1,2}))$/
```
### 数字/货币金额 (只支持正数、不支持校验千分位分隔符)
```javascript
/(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0){1}$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/
```
### 银行卡号10到30位, 覆盖对公/私账户, 参考[微信支付](https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=22_1)
```javascript
/^[1-9]\d{9,29}$/
```
### 中文姓名
```javascript
/^(?:[\u4e00-\u9fa5·]{2,16})$/
```
### 英文姓名
```javascript
/(^[a-zA-Z]{1}[a-zA-Z\s]{0,20}[a-zA-Z]{1}$)/
```
### 新能源车牌号
```javascript
/[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$/
```
### 非新能源车牌号
```javascript
/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/
```
### 车牌号(新能源+非新能源)
```javascript
/^(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(?:(?:[0-9]{5}[DF])|(?:[DF](?:[A-HJ-NP-Z0-9])[0-9]{4})))|(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 挂学警港澳]{1})$/
```
### 中国手机号(严谨), 根据工信部2019年最新公布的手机号段
```javascript
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1|8|9]))\d{8}$/
```
### 中国手机号(宽松), 只要是13,14,15,16,17,18,19开头即可
```javascript
/^(?:(?:\+|00)86)?1[3-9]\d{9}$/
```
### 中国手机号(最宽松), 只要是1开头即可, 如果你的手机号是用来接收短信, 优先建议选择这一条
```javascript
/^(?:(?:\+|00)86)?1\d{10}$/
```
### 日期
```javascript
/^\d{4}(-)(1[0-2]|0?\d)\1([0-2]\d|\d|30|31)$/
```
### 邮箱地址(email)
```javascript
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
```
### 国内座机电话,如: 0341-86091234
```javascript
/\d{3}-\d{8}|\d{4}-\d{7}/
```
### 一代身份证号(15位数字)
```javascript
/^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$/
```
### 二代身份证号(18位数字),最后一位是校验位,可能为数字或字符X
```javascript
/^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}[\dXx]$/
```
### 身份证号, 支持1/2代(15位/18位数字)
```javascript
/(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/
```
### 护照(包含香港、澳门)
```javascript
/(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/
```
### 帐号是否合法(字母开头允许5-16字节允许字母数字下划线组合
```javascript
/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/
```
### 纯中文/汉字
```javascript
/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/
```
### 是否小数
```javascript
/^\d+\.\d+$/
```
### 电话(座机)
```javascript
/^0\d{2,3}-\d{7,8}$/
```
### 纯数字
```javascript
/^\d{1,}$/
```
### 是否html标签(宽松匹配)
```javascript
/<(.*)>.*<\/\1>|<(.*) \/>/
```
### 是否qq号格式正确
```javascript
/^[1-9][0-9]{4,10}$/
```
### 是否由数字和字母组成
```javascript
/^[A-Za-z0-9]+$/
```
### 纯英文字母
```javascript
/^[a-zA-Z]+$/
```
### 纯小写英文字母组成
```javascript
/^[a-z]+$/
```
### 纯大写英文字母
```javascript
/^[A-Z]+$/
```
### 密码强度校验最少6位包括至少1个大写字母1个小写字母1个数字1个特殊字符
```javascript
/^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/
```
### 用户名校验4到16位字母数字下划线减号
```javascript
/^[a-zA-Z0-9_-]{4,16}$/
```
### ip-v4
```javascript
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
```
### ip-v6
```javascript
/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
```
### 16进制颜色
```javascript
/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
```
### 微信号6至20位以字母开头字母数字减号下划线
```javascript
/^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/
```
### 中国邮政编码
```javascript
/^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/
```
### 只包含中文和数字
```javascript
/^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/
```
### 不能包含字母
```javascript
/^[^A-Za-z]*$/
```

View File

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require("vscode");
const RULES = require('../packages/www/src/RULES.js');
const vscode_1 = require("vscode");
const anyrule_1 = require("./anyrule");
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
function activate(context) {
@ -14,38 +14,45 @@ function activate(context) {
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
// let disposable = vscode.commands.registerCommand('extension.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
// vscode.window.showInformationMessage('Hello World123!');
// // The code you place here will be executed every time your command is executed
// // Display a message box to the user
// vscode.window.showInformationMessage('Hello World!');
// });
// context.subscriptions.push(disposable);
RULES.forEach(({ title, rule }, index) => {
let disposable = vscode.commands.registerCommand(`extension.rule${index}`, () => {
// The code you place here will be executed every time your command is executed
const editor = vscode.window.activeTextEditor;
if (editor) {
const { selections } = editor;
editor.edit(editBuilder => {
selections.forEach(selection => {
const { start, end } = selection;
const range = new vscode.Range(start, end);
editBuilder.replace(range, String(rule));
});
const anyRule = new anyrule_1.AnyRule(context);
vscode_1.workspace.onDidChangeConfiguration((event) => {
anyRule.reload();
});
vscode_1.commands.registerCommand('extension.update', () => {
anyRule.update();
});
vscode_1.commands.registerCommand('extension.reload', () => {
anyRule.reload();
vscode_1.window.showInformationMessage('重新加载插件成功');
});
vscode_1.commands.registerCommand('extension.support', () => {
var _a;
const currentLanguage = (_a = vscode_1.window.activeTextEditor) === null || _a === void 0 ? void 0 : _a.document.languageId;
if (currentLanguage) {
try {
const configuration = vscode_1.workspace.getConfiguration();
const setting = configuration.get('anyRule.supportedLanguages') || 'javascript,typescirpt';
const supportedLanguages = setting.split(',');
const set = new Set(supportedLanguages);
set.add(currentLanguage);
console.log(Array.from(set).join(','));
configuration.update('anyRule.supportedLanguages', Array.from(set).join(',')).then(() => {
anyRule.reload();
});
// Display a message box to the user
vscode.window.showInformationMessage(`已插入正则: ${title}`);
vscode_1.window.showInformationMessage('更新关联语言成功');
}
else {
vscode.window.showWarningMessage('any-rule: 只有在编辑文本的时候才可以使用!');
catch (e) {
vscode_1.window.showInformationMessage('更新关联语言失败');
}
});
context.subscriptions.push(disposable);
}
});
}
exports.activate = activate;
// this method is called when your extension is deactivated
function deactivate() {
vscode.window.showWarningMessage('any-rule: 已关闭!');
}
function deactivate() { }
exports.deactivate = deactivate;
//# sourceMappingURL=extension.js.map

View File

@ -1 +1 @@
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,iCAAiC;AACjC,MAAM,KAAK,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;AACtD,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IACxD,4FAA4F;IAC5F,gFAAgF;IAChF,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;IAEzE,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IAGvE,mFAAmF;IACnF,+EAA+E;IAE/E,oCAAoC;IACpC,2DAA2D;IAC3D,MAAM;IACN,0CAA0C;IAE1C,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAoD,EAAE,KAAa,EAAE,EAAE;QAClG,IAAI,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,iBAAiB,KAAK,EAAE,EAAE,GAAG,EAAE;YAC/E,+EAA+E;YAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC9C,IAAI,MAAM,EAAE;gBACX,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;gBAE9B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;oBACzB,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;wBAC9B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;wBACjC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;wBAC3C,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC1C,CAAC,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,oCAAoC;gBACpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;aACxD;iBAAM;gBACN,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,4BAA4B,CAAC,CAAC;aAC/D;QACF,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AAIJ,CAAC;AA3CD,4BA2CC;AAED,2DAA2D;AAC3D,SAAgB,UAAU;IACzB,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;AACpD,CAAC;AAFD,gCAEC"}
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,mCAGgB;AAEhB,uCAAoC;AAEpC,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAyB;IAEjD,4FAA4F;IAC5F,gFAAgF;IAChF,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;IAEzE,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IACvE,mFAAmF;IACnF,mFAAmF;IAEnF,wCAAwC;IACxC,yDAAyD;IACzD,MAAM;IACN,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,OAAO,CAAC,CAAC;IAErC,kBAAS,CAAC,wBAAwB,CAAC,CAAC,KAA+B,EAAE,EAAE;QACtE,OAAO,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,iBAAQ,CAAC,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACjD,OAAO,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,iBAAQ,CAAC,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACjD,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,eAAM,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,iBAAQ,CAAC,eAAe,CAAC,mBAAmB,EAAE,GAAG,EAAE;;QAClD,MAAM,eAAe,SAAG,eAAM,CAAC,gBAAgB,0CAAE,QAAQ,CAAC,UAAU,CAAC;QACrE,IAAI,eAAe,EAAE;YACpB,IAAI;gBACH,MAAM,aAAa,GAAG,kBAAS,CAAC,gBAAgB,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAW,aAAa,CAAC,GAAG,CAAC,4BAA4B,CAAC,IAAI,uBAAiC,CAAC;gBAC7G,MAAM,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC;gBACxC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACvC,aAAa,CAAC,MAAM,CAAC,4BAA4B,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;oBACvF,OAAO,CAAC,MAAM,EAAE,CAAC;gBAClB,CAAC,CAAC,CAAC;gBACH,eAAM,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;aAC1C;YAAC,OAAM,CAAC,EAAE;gBACV,eAAM,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;aAC1C;SACD;IACF,CAAC,CAAC,CAAC;AACJ,CAAC;AA/CD,4BA+CC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAK,CAAC;AAAhC,gCAAgC"}

View File

@ -19,316 +19,43 @@
"url": "git+https://github.com/any86/any-rule.git"
},
"activationEvents": [
"onCommand:extension.rule0",
"onCommand:extension.rule1",
"onCommand:extension.rule2",
"onCommand:extension.rule3",
"onCommand:extension.rule4",
"onCommand:extension.rule5",
"onCommand:extension.rule6",
"onCommand:extension.rule7",
"onCommand:extension.rule8",
"onCommand:extension.rule9",
"onCommand:extension.rule10",
"onCommand:extension.rule11",
"onCommand:extension.rule12",
"onCommand:extension.rule13",
"onCommand:extension.rule14",
"onCommand:extension.rule15",
"onCommand:extension.rule16",
"onCommand:extension.rule17",
"onCommand:extension.rule18",
"onCommand:extension.rule19",
"onCommand:extension.rule20",
"onCommand:extension.rule21",
"onCommand:extension.rule22",
"onCommand:extension.rule23",
"onCommand:extension.rule24",
"onCommand:extension.rule25",
"onCommand:extension.rule26",
"onCommand:extension.rule27",
"onCommand:extension.rule28",
"onCommand:extension.rule29",
"onCommand:extension.rule30",
"onCommand:extension.rule31",
"onCommand:extension.rule32",
"onCommand:extension.rule33",
"onCommand:extension.rule34",
"onCommand:extension.rule35",
"onCommand:extension.rule36",
"onCommand:extension.rule37",
"onCommand:extension.rule38",
"onCommand:extension.rule39",
"onCommand:extension.rule40",
"onCommand:extension.rule41",
"onCommand:extension.rule42",
"onCommand:extension.rule43",
"onCommand:extension.rule44",
"onCommand:extension.rule45",
"onCommand:extension.rule46",
"onCommand:extension.rule47",
"onCommand:extension.rule48",
"onCommand:extension.rule49",
"onCommand:extension.rule50",
"onCommand:extension.rule51",
"onCommand:extension.rule52",
"onCommand:extension.rule53",
"onCommand:extension.rule54",
"onCommand:extension.rule55",
"onCommand:extension.rule56",
"onCommand:extension.rule57",
"onCommand:extension.rule58",
"onCommand:extension.rule59",
"onCommand:extension.rule60"
"onCommand:extension.update",
"onCommand:extension.reload",
"onCommand:extension.support",
"*"
],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "extension.rule0",
"title": "zz: 火车车次"
},
{
"command": "extension.rule1",
"title": "zz: 手机机身码(IMEI)"
},
{
"command": "extension.rule2",
"title": "zz: 必须带端口号的网址(或ip)"
},
{
"command": "extension.rule3",
"title": "zz: 网址(支持端口和\"?+参数\"和\"#+参数)"
},
{
"command": "extension.rule4",
"title": "zz: 统一社会信用代码"
},
{
"command": "extension.rule5",
"title": "zz: 迅雷链接"
},
{
"command": "extension.rule6",
"title": "zz: ed2k链接(宽松匹配)"
},
{
"command": "extension.rule7",
"title": "zz: 磁力链接(宽松匹配)"
},
{
"command": "extension.rule8",
"title": "zz: 子网掩码"
},
{
"command": "extension.rule9",
"title": "zz: linux\"文件夹\"路径"
},
{
"command": "extension.rule10",
"title": "zz: linux\"文件\"路径"
},
{
"command": "extension.rule11",
"title": "zz: window下\"文件夹\"路径"
},
{
"command": "extension.rule12",
"title": "zz: window下\"文件\"路径"
},
{
"command": "extension.rule13",
"title": "zz: A股代码"
},
{
"command": "extension.rule14",
"title": "zz: 大于等于0, 小于等于150, 支持小数位出现5, 如145.5, 用于判断考卷分数"
},
{
"command": "extension.rule15",
"title": "zz: html注释"
},
{
"command": "extension.rule16",
"title": "zz: md5格式(32位)"
},
{
"command": "extension.rule17",
"title": "zz: 版本号格式必须为X.Y.Z"
},
{
"command": "extension.rule18",
"title": "zz: 视频链接地址(视频格式可按需增删)"
},
{
"command": "extension.rule19",
"title": "zz: 图片链接地址(图片格式可按需增删)"
},
{
"command": "extension.rule20",
"title": "zz: 24小时制时间HH:mm:ss"
},
{
"command": "extension.rule21",
"title": "zz: 12小时制时间hh:mm:ss"
},
{
"command": "extension.rule22",
"title": "zz: base64格式"
},
{
"command": "extension.rule23",
"title": "zz: 数字/货币金额(支持负数、千分位分隔符)"
},
{
"command": "extension.rule24",
"title": "zz: 数字/货币金额 (只支持正数、不支持校验千分位分隔符)"
},
{
"command": "extension.rule25",
"title": "zz: 银行卡号10到30位, 覆盖对公/私账户, 参考[微信支付](https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=22_1)"
},
{
"command": "extension.rule26",
"title": "zz: 中文姓名"
},
{
"command": "extension.rule27",
"title": "zz: 英文姓名"
},
{
"command": "extension.rule28",
"title": "zz: 新能源车牌号"
},
{
"command": "extension.rule29",
"title": "zz: 非新能源车牌号"
},
{
"command": "extension.rule30",
"title": "zz: 车牌号(新能源+非新能源)"
},
{
"command": "extension.rule31",
"title": "zz: 中国手机号(严谨), 根据工信部2019年最新公布的手机号段"
},
{
"command": "extension.rule32",
"title": "zz: 中国手机号(宽松), 只要是13,14,15,16,17,18,19开头即可"
},
{
"command": "extension.rule33",
"title": "zz: 中国手机号(最宽松), 只要是1开头即可, 如果你的手机号是用来接收短信, 优先建议选择这一条"
},
{
"command": "extension.rule34",
"title": "zz: 日期"
},
{
"command": "extension.rule35",
"title": "zz: 邮箱地址(email)"
},
{
"command": "extension.rule36",
"title": "zz: 国内座机电话,如: 0341-86091234"
},
{
"command": "extension.rule37",
"title": "zz: 一代身份证号(15位数字)"
},
{
"command": "extension.rule38",
"title": "zz: 二代身份证号(18位数字),最后一位是校验位,可能为数字或字符X"
},
{
"command": "extension.rule39",
"title": "zz: 身份证号, 支持1/2代(15位/18位数字)"
},
{
"command": "extension.rule40",
"title": "zz: 护照(包含香港、澳门)"
},
{
"command": "extension.rule41",
"title": "zz: 帐号是否合法(字母开头允许5-16字节允许字母数字下划线组合"
},
{
"command": "extension.rule42",
"title": "zz: 纯中文/汉字"
},
{
"command": "extension.rule43",
"title": "zz: 是否小数"
},
{
"command": "extension.rule44",
"title": "zz: 电话(座机)"
},
{
"command": "extension.rule45",
"title": "zz: 纯数字"
},
{
"command": "extension.rule46",
"title": "zz: 是否html标签(宽松匹配)"
},
{
"command": "extension.rule47",
"title": "zz: 是否qq号格式正确"
},
{
"command": "extension.rule48",
"title": "zz: 是否由数字和字母组成"
},
{
"command": "extension.rule49",
"title": "zz: 纯英文字母"
},
{
"command": "extension.rule50",
"title": "zz: 纯小写英文字母组成"
},
{
"command": "extension.rule51",
"title": "zz: 纯大写英文字母"
},
{
"command": "extension.rule52",
"title": "zz: 密码强度校验最少6位包括至少1个大写字母1个小写字母1个数字1个特殊字符"
},
{
"command": "extension.rule53",
"title": "zz: 用户名校验4到16位字母数字下划线减号"
},
{
"command": "extension.rule54",
"title": "zz: ip-v4"
},
{
"command": "extension.rule55",
"title": "zz: ip-v6"
},
{
"command": "extension.rule56",
"title": "zz: 16进制颜色"
},
{
"command": "extension.rule57",
"title": "zz: 微信号6至20位以字母开头字母数字减号下划线"
},
{
"command": "extension.rule58",
"title": "zz: 中国邮政编码"
},
{
"command": "extension.rule59",
"title": "zz: 只包含中文和数字"
},
{
"command": "extension.rule60",
"title": "zz: 不能包含字母"
}
]
{
"command": "extension.update",
"title": "Any Rule: 更新正则数据"
},
{
"command": "extension.reload",
"title": "Any Rule: 重新加载插件"
},
{
"command": "extension.support",
"title": "Any Rule: 支持当前文件类型"
}
],
"configuration": {
"type": "object",
"title": "Any Rule",
"properties": {
"anyRule.triggerString": {
"type": "string",
"default": "zz",
"description": "触发字符串"
},
"anyRule.supportedLanguages": {
"type": "string",
"default": "javascript,typescript",
"description": "激活AnyRule的文件类型多个类型用逗号分隔"
}
}
}
},
"scripts": {
"build:md": "node ./scripts/md.js",
@ -340,15 +67,20 @@
"test": "node ./out/test/runTest.js",
"test:rules": "node __test__/rule"
},
"dependencies": {
"axios": "^0.19.0",
"pinyin": "^2.9.0"
},
"devDependencies": {
"@types/glob": "^7.1.1",
"@types/mocha": "^5.2.6",
"@types/node": "^10.12.21",
"@types/vscode": "^1.12.0",
"glob": "^7.1.4",
"mocha": "^6.1.4",
"typescript": "^3.3.1",
"tslint": "^5.12.1",
"vscode-test": "^1.0.2"
"@types/mocha": "^5.2.7",
"@types/node": "^12.11.7",
"@types/vscode": "^1.41.0",
"@types/pinyin": "^2.8.1",
"glob": "^7.1.5",
"mocha": "^6.2.2",
"tslint": "^5.20.0",
"typescript": "^3.6.4",
"vscode-test": "^1.2.2"
}
}

View File

@ -1,21 +0,0 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 any86
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/app'
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
{
"name": "any-rule",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:demo": "npm run build && node ./scripts/demo",
"lint": "vue-cli-service lint"
},
"dependencies": {
"clipboard": "^2.0.4",
"core-js": "^2.6.5",
"lodash": "^4.17.13",
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",
"vue": "^2.6.10"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.8.0",
"@vue/cli-plugin-eslint": "^3.8.0",
"@vue/cli-service": "^3.8.0",
"chalk": "^2.4.2",
"gh-pages": "^2.0.1",
"shelljs": "^0.8.3",
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}

View File

@ -1,8 +0,0 @@
// prettier.config.js or .prettierrc.js
module.exports = {
tabWidth: 4,
semi: true,
singleQuote: true,
arrowParens: 'always',
printWidth: 120
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,87 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>正则大全</title>
<!-- 百度统计 -->
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?0a8aba0d0567d5e3b7fa2c9eac9d781f";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<!-- <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.8/styles/github.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.8/highlight.min.js"></script> -->
<style>
:root{
--primary: #42b983;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow-x: hidden;
overflow-y: scroll;
}
a {
text-decoration: none;
}
input {
outline: none;
border: 0 none;
}
li {
list-style-type: none;
}
@keyframes rotate{
from{
transform: rotate(0);
}
to{
transform: rotate(360deg);
}
}
.loading{
animation: rotate 1s infinite linear;
margin:0;
padding:0;
position: fixed;
top:0;left:0;right: 0;bottom:0;
margin:auto;
display: block;
width:100px;
height:100px;
border:0 solid #42b983;
border-right-width: 4px;
border-radius: 50%;
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but any-rule doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<i class="loading"></i>
</div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,15 +0,0 @@
var ghpages = require('gh-pages');
const shell = require('shelljs');
const chalk = require('chalk');
// 发布
ghpages.publish('./dist', {
branch: 'gh-pages',
}, (err) => {
if(err) {
console.log(chalk.red(err));
} else {
shell.rm('-rf', './dist');
console.log(chalk.green('demo同步完成!'));
}
});

View File

@ -1,459 +0,0 @@
<template>
<main>
<article class="fixed">
<a
onclick="_hmt.push(['_trackEvent', '交互', '点击github', '悬浮'])"
href="https://github.com/any86/any-rule"
target="_blank"
class="github"
>
<svg height="20" viewBox="0 0 16 16" version="1.1" width="20" aria-hidden="true">
<path
fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
<span>github</span>
</a>
<a
onclick="_hmt.push(['_trackEvent', '交互', '提问'])"
class="message"
href="https://github.com/any86/any-rule/issues/new"
target="_blank"
>提问</a>
</article>
<header>
<h1>正则大全</h1>
<a
onclick="_hmt.push(['_trackEvent', '交互', '点击github', '头部'])"
style="margin-left:15px;color:#000;"
href="https://github.com/any86/any-rule"
target="_blank"
class="github"
>
<svg height="20" viewBox="0 0 16 16" version="1.1" width="20" aria-hidden="true">
<path
fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
<span>github</span>
</a>
<iframe style="display:block;margin-top:15px;" src="https://ghbtns.com/github-btn.html?user=any86&repo=any-rule&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe>
<input
ref="searchInput"
v-model="keyword"
autofocus
@keyup="search"
@mouseenter="selectSearchInputText"
@focus="selectSearchInputText"
class="search-input"
placeholder="搜索关键词, 如'手机'"
type="text"
>
</header>
<article>
<ul v-if="0 < rules.length" class="list">
<li
@mouseenter="mouseenterHandler(index)"
v-for="({title, rule, events,examples,counterExamples}, index) in rules"
:key="title"
class="row"
>
<i class="border"></i>
<h2>{{title}}</h2>
<p class="rule">
<span :data-clipboard-text="rule" class="btn-copy">点击复制</span>
<a
:href="`https://github.com/any86/any-rule/issues/new?title=我有更好的正则: ${title}`"
target="_blank"
class="btn-better"
>我有更好的正则</a>
<code ref="code" class="javascript">{{rule}}</code>
</p>
<section class="verification">
<label>
<input
ref="input"
:key="title"
v-model="list[index].value"
:placeholder="parseExample(examples, counterExamples)"
@compositionstart="check(index, 'blur')"
@compositionupdate="check(index, 'blur')"
@compositionend="check(index, 'blur')"
@blur="check(index, 'blur')"
@keyup="check(index, 'keyup')"
>
<span class="btn-clear" @click="reset(index)">清空</span>
</label>
<div class="tip">
<template v-if="undefined !== list[index].isOk">
<p v-if="list[index].isOk" class="success">通过</p>
<p v-else class="error">不通过</p>
</template>
</div>
</section>
<section class="trigger">
<h3>验证时机</h3>
<label>
<input v-model="list[index].events.blur" type="checkbox"> blur
</label>
<label>
<input v-model="list[index].events.keyup" type="checkbox"> keyup
</label>
</section>
</li>
</ul>
<p v-else align="center">无数据</p>
</article>
</main>
</template>
<script>
import RULES from '@/RULES';
import ClipboardJS from 'clipboard';
// import throttle from 'lodash/throttle';
export default {
name: 'app',
components: {},
data() {
Object.freeze(RULES);
return {
timer: null,
keyword: '',
rules: RULES,
list: RULES.map(() => ({
value: '',
isOk: undefined,
events: {
blur: true,
keyup: true
}
}))
};
},
mounted() {
// this.$nextTick(() => {
// //
// this.$refs.code.forEach((block) => {
// console.log(block);
// /* eslint-disable */
// hljs.highlightBlock(block);
// });
// });
const clipboard = new ClipboardJS('.btn-copy');
this.$on('hook:destroyed', () => {
clipboard.destroy();
});
let timer = null;
clipboard.on('success', (e) => {
clearTimeout(timer);
const el = e.trigger;
if (el.classList.contains('success')) {
el.classList.remove('success');
}
el.classList.add('success');
timer = setTimeout(() => {
el.classList.remove('success');
}, 1000);
});
},
methods: {
parseExample(examples, counterExamples){
let arr = [`例如: ${examples.join(', ')}`];
if(undefined !== counterExamples) {
arr.push(`反例: ${counterExamples.join(', ')}`);
}
return arr.join(' , ');
},
search() {
if ('' !== this.keyword) {
this.rules = this.rules.filter(({ title }) => -1 !== title.indexOf(this.keyword.toLowerCase()));
} else {
this.rules = RULES;
}
/* eslint-disable */
_hmt.push(['_trackEvent', '交互', '搜索', '关键词', this.keyword]);
},
selectSearchInputText() {
this.$refs.searchInput.select();
},
autoFocus(index) {
this.$refs.input[index].focus();
},
/* eslint-disable */
mouseenterHandler(index) {},
// mouseenterHandler: throttle((index)=>{
// this.$refs.input[index].focus();
// },1000).bind(this),
reset(index) {
this.$nextTick(() => {
this.list[index].value = '';
this.list[index].isOk = undefined;
});
},
check(index, type) {
const { events, value } = this.list[index];
if ('' === value) this.reset(index);
if (events[type]) {
const { rule } = this.rules[index];
const row = this.list[index];
row.isOk = rule.test(row.value);
}
if ('blur' === type) {
/* eslint-disable */
_hmt.push(['_trackEvent', 'input框', this.rules[index].title, this.list[index].value]);
}
}
}
};
</script>
<style lang="scss" scoped>
$primary: #42b983;
$danger: #ec5c51;
$radius: 4px;
@keyframes slide {
from {
top: 0;
}
to {
top: 100px;
}
}
@keyframes shrinkBorder {
from {
transform: translateY(-100%);
}
50% {
width: 4px;
opacity: 0.62;
}
to {
left: 0;
transform: translateY(0);
}
}
main {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
max-width: 1000px;
width: 100%;
margin: auto;
.fixed {
position: fixed;
z-index: 1986;
right: 15px;
bottom: 15px;
box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.1);
border-radius: $radius;
overflow: hidden;
> a {
display: flex;
align-content: center;
align-items: center;
justify-content: center;
justify-items: center;
font-size: 16px;
text-align: center;
padding: 15px;
&:active {
opacity: 0.6;
box-shadow: none;
}
&:hover {
opacity: 0.6;
}
&.github {
background: rgba(#eee, 0.9);
> span {
color: #000;
padding: 0 10px;
}
}
&.message {
background: rgba($primary, 0.9);
color: #fff;
}
}
}
header {
padding: 15px;
> .search-input {
display: block;
margin-top: 15px;
font-size: 16px;
border: 1px solid #ddd;
width: 100%;
padding: 15px;
border-radius: $radius;
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.1);
}
h1 {
display: inline-block;
}
>.github{display: inline-flex;
>span{
margin-left: 5px;
}
}
}
ul.list {
padding: 15px;
li {
position: relative;
overflow: hidden;
border-radius: $radius;
margin-bottom: 15px;
padding: 15px;
border-color: #eee;
border-width: 1px;
border-style: solid;
> .border {
position: absolute;
background: $primary;
width: 4px;
height: 100%;
top: 0;
left: -4px;
}
&:hover {
background-color: #ddd;
transition: all 600ms;
border-radius: $radius;
border-color: #eee;
> .border {
animation: shrinkBorder 0.5s;
left: 0;
}
}
> p.rule {
margin-top: 15px;
padding: 5px 15px;
background: #eee;
color: #000;
border-radius: $radius;
line-height: 2;
> .btn-copy {
display: inline-block;
border-radius: $radius;
margin-right: 15px;
padding:0 5px;
background: $primary;
color: #fff;
font-size: 12px;
cursor: pointer;
&.success {
&:after {
content: '复制成功';
border-radius: $radius;
display: block;
padding: 5px 15px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
text-align: center;
position: absolute;
}
}
&:active {
opacity: 0.6;
color: #444;
}
&:hover {
opacity: 0.6;
}
}
> .btn-better {
@extend .btn-copy;
background-color: $danger;
}
>code{word-break:break-word;}
}
> section.verification {
margin-top: 15px;
overflow: hidden;
> label {
display: flex;
> input {
flex-grow: 1;
padding: 5px 15px;
border-radius: $radius;
border: 1px solid #ddd;
font-size: 16px;
& + .btn-clear {
padding: 5px;
color: #000;
display: inline-block;
font-size: 14px;
&:active {
color: #ccc;
}
&:hover {
color: #666;
}
}
}
}
> .tip {
height: 24px;
padding: 5px;
> p {
font-size: 14px;
&.success {
color: #4caf50;
}
&.error {
color: #ff5722;
}
}
}
}
> section.trigger {
display: flex;
align-items: center;
align-content: center;
h3 {
font-size: 14px;
}
> label {
padding: 0 10px;
}
}
}
}
}
</style>

View File

@ -1,313 +0,0 @@
module.exports = [{
title: '火车车次',
rule: /^[GCDZTSPKXLY1-9]\d{1,4}$/,
examples: ['G1868', 'D102', 'D9', 'Z5', 'Z24', 'Z17']
},
{
title: '手机机身码(IMEI)',
rule: /^\d{15,17}$/,
examples: ['123456789012345', '1234567890123456', '12345678901234567']
},
{
title: '必须带端口号的网址(或ip)',
rule: /^(((ht|f)tps?):\/\/)?[\w\-]+(\.[\w\-]+)+:\d{0,5}\/?/,
examples: ['https://www.qq.com:8080', '127.0.0.1:5050', 'baidu.com:8001', 'http://192.168.1.1:9090'],
counterExamples: ['192.168.1.1', 'https://www.jd.com']
},
{
title: '网址(支持端口和"?+参数"和"#+参数)',
rule: /^(((ht|f)tps?):\/\/)?[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/,
examples: ['www.qq.com', 'https://baidu.com', '360.com:8080/vue/#/a=1&b=2'],
counterExamples: ['....']
},
{
title: '统一社会信用代码',
rule: /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/,
examples: ['91230184MA1BUFLT44', '92371000MA3MXH0E3W'],
},
{
title: '迅雷链接',
rule: /^thunderx?:\/\/[a-zA-Z\d]+=$/,
examples: ['thunder://QUEsICdtYWduZXQ6P3h0PXVybjpidGloOjBCQTE0RTUxRkUwNjU1RjE0Qzc4NjE4RjY4NDY0QjZFNTEyNjcyOUMnWlo='],
},
{
title: 'ed2k链接(宽松匹配)',
rule: /^ed2k:\/\/\|file\|.+\|\/$/,
examples: ['ed2k://|file|%E5%AF%84%E7%94%9F%E8%99%AB.PARASITE.2019.HD-1080p.X264.AAC-UUMp4(ED2000.COM).mp4|2501554832|C0B93E0879C6071CBED732C20CE577A3|h=5HTKZPQFYRKORN52I3M7GQ4QQCIHFIBV|/'],
},
{
title: '磁力链接(宽松匹配)',
rule: /^magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*$/,
examples: ['magnet:?xt=urn:btih:40A89A6F4FB1498A98087109D012A9A851FBE0FC'],
},
{
title: '子网掩码',
rule: /^(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/,
examples: ['255.255.255.0', '255.224.0.0']
},
{
title: 'linux"文件夹"路径',
rule: /^\/(\w+\/?)+$/,
examples: ['/usr/ad/dd', '/root/']
},
{
title: 'linux"文件"路径',
rule: /^\/(\w+\/)+\w+\.\w+$/,
examples: ['/usr/ad/dd/a.js', '/root/b.ts']
},
{
title: 'window下"文件夹"路径',
rule: /^[a-zA-Z]:\\(?:\w+\\?)*$/,
examples: ['C:\\Users\\Administrator\\Desktop', 'e:\\m\\']
},
{
title: 'window下"文件"路径',
rule: /^[a-zA-Z]:\\(?:\w+\\)*\w+\.\w+$/,
examples: ['C:\\Users\\Administrator\\Desktop\\qq.link', 'e:\\m\\vscode.exe']
},
{
title: 'A股代码',
rule: /^(s[hz]|S[HZ])(000[\d]{3}|002[\d]{3}|300[\d]{3}|600[\d]{3}|60[\d]{4})$/,
examples: ['sz000858', 'SZ002136', 'sz300675', 'SH600600', 'sh601155']
},
{
title: '大于等于0, 小于等于150, 支持小数位出现5, 如145.5, 用于判断考卷分数',
rule: /^150$|^(?:\d|[1-9]\d|1[0-4]\d)(?:.5)?$/,
examples: [150, 100.5]
},
{
title: 'html注释',
rule: /^<!--[\s\S]*?-->$/,
examples: ['<!--<div class="_bubble"></div>-->']
},
{
title: 'md5格式(32位)',
rule: /^[a-f0-9]{32}$/,
examples: ['21fe181c5bfc16306a6828c1f7b762e8'],
},
{
title: '版本号格式必须为X.Y.Z',
rule: /^\d+(?:\.\d+){2}$/,
examples: ['16.3.10']
},
{
title: '视频链接地址(视频格式可按需增删)',
rule: /^https?:\/\/(.+\/)+.+(\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|mp4))$/i,
examples: ['http://www.abc.com/video/wc.avi']
},
{
title: '图片链接地址(图片格式可按需增删)',
rule: /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
examples: ['https://www.abc.com/logo.png']
},
{
title: '24小时制时间HH:mm:ss',
rule: /^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/,
examples: ['23:34:55']
},
{
title: '12小时制时间hh:mm:ss',
rule: /^(?:1[0-2]|0?[1-9]):[0-5]\d:[0-5]\d$/,
examples: ['11:34:55'],
counterExamples: ['23:34:55']
},
{
title: 'base64格式',
rule: /^\s*data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)?)?(?:;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*?)\s*$/i,
examples: ['data:image/gif;base64,xxxx==']
},
{
title: '数字/货币金额(支持负数、千分位分隔符)',
rule: /(?:^[-]?[1-9]\d{0,2}(?:$|(?:,\d{3})*(?:$|(\.\d{1,2}$))))|(?:(?:^[0](\.\d{1,2})?)|(?:^[-][0]\.\d{1,2}))$/,
examples: [100, -0.99, 3, 234.32, -1, 900, 235.09]
},
{
title: '数字/货币金额 (只支持正数、不支持校验千分位分隔符)',
rule: /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0){1}$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/,
examples: [0.99, 8.99, 666]
},
{
title: '银行卡号10到30位, 覆盖对公/私账户, 参考[微信支付](https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=22_1)',
rule: /^[1-9]\d{9,29}$/,
examples: [6234567890, 6222026006705354217]
},
{
title: '中文姓名',
rule: /^(?:[\u4e00-\u9fa5·]{2,16})$/,
examples: ['葛二蛋', '凯文·杜兰特', '德克·维尔纳·诺维茨基']
},
{
title: '英文姓名',
rule: /(^[a-zA-Z]{1}[a-zA-Z\s]{0,20}[a-zA-Z]{1}$)/,
examples: ['James', 'Kevin Wayne Durant', 'Dirk Nowitzki']
},
{
title: '新能源车牌号',
rule: /[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$/,
examples: ['京AD92035', '甘G23459F'],
},
{
title: '非新能源车牌号',
rule: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/,
examples: ['京A00599', '黑D23908']
},
{
title: '车牌号(新能源+非新能源)',
rule: /^(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(?:(?:[0-9]{5}[DF])|(?:[DF](?:[A-HJ-NP-Z0-9])[0-9]{4})))|(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 挂学警港澳]{1})$/,
examples: ['京A12345D', '京A00599']
},
{
title: '中国手机号(严谨), 根据工信部2019年最新公布的手机号段',
rule: /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1|8|9]))\d{8}$/,
examples: ['008618311006933', '+8617888829981', '19119255642']
},
{
title: '中国手机号(宽松), 只要是13,14,15,16,17,18,19开头即可',
rule: /^(?:(?:\+|00)86)?1[3-9]\d{9}$/,
examples: ['008618311006933', '+8617888829981', '19119255642']
},
{
title: '中国手机号(最宽松), 只要是1开头即可, 如果你的手机号是用来接收短信, 优先建议选择这一条',
rule: /^(?:(?:\+|00)86)?1\d{10}$/,
examples: ['008618311006933', '+8617888829981', '19119255642']
},
{
title: '日期',
rule: /^\d{4}(-)(1[0-2]|0?\d)\1([0-2]\d|\d|30|31)$/,
examples: ['1990-12-12', '2020-1-1']
},
{
title: '邮箱地址(email)',
rule: /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
examples: ['90203918@qq.com', 'nbilly@126.com']
},
{
title: '国内座机电话,如: 0341-86091234',
rule: /\d{3}-\d{8}|\d{4}-\d{7}/,
examples: ['0936-4211235']
},
{
title: '一代身份证号(15位数字)',
rule: /^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$/,
examples: ['622001790131123']
},
{
title: '二代身份证号(18位数字),最后一位是校验位,可能为数字或字符X',
rule: /^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}[\dXx]$/,
examples: ['62222319991205131x']
},
{
title: '身份证号, 支持1/2代(15位/18位数字)',
rule: /(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/,
examples: ['622223199912051311']
},
{
title: '护照(包含香港、澳门)',
rule: /(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/,
examples: ['s28233515', '141234567', '159203084', 'MA1234567', 'K25345719']
},
{
title: '帐号是否合法(字母开头允许5-16字节允许字母数字下划线组合',
rule: /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/,
examples: ['justin', 'justin1989', 'justin_666']
},
{
title: '纯中文/汉字',
// rule: /^[\u4E00-\u9FA5]+$/,
rule: /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/,
examples: ['正则', '前端']
},
{
title: '是否小数',
rule: /^\d+\.\d+$/,
examples: ['0.0', '0.09']
},
{
title: '电话(座机)',
rule: /^0\d{2,3}-\d{7,8}$/,
examples: ['0936-4211236']
},
{
title: '纯数字',
rule: /^\d{1,}$/,
examples: [12345678]
},
{
title: '是否html标签(宽松匹配)',
rule: /<(.*)>.*<\/\1>|<(.*) \/>/,
examples: ['<div> </div>']
},
{
title: '是否qq号格式正确',
rule: /^[1-9][0-9]{4,10}$/,
examples: [903013545, 9020304]
},
{
title: '是否由数字和字母组成',
rule: /^[A-Za-z0-9]+$/,
examples: ['james666', 'haha233hi']
},
{
title: '纯英文字母',
rule: /^[a-zA-Z]+$/,
examples: ['Russel']
},
{
title: '纯小写英文字母组成',
rule: /^[a-z]+$/,
examples: ['russel']
},
{
title: '纯大写英文字母',
rule: /^[A-Z]+$/,
examples: ['ABC', 'KD']
},
{
title: '密码强度校验最少6位包括至少1个大写字母1个小写字母1个数字1个特殊字符',
rule: /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/,
examples: ['Kd@curry666']
},
{
title: '用户名校验4到16位字母数字下划线减号',
rule: /^[a-zA-Z0-9_-]{4,16}$/,
examples: ['xiaohua_qq']
},
{
title: 'ip-v4',
rule: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
examples: ['172.16.0.0', '127.0.0.0']
},
{
title: 'ip-v6',
rule: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i,
examples: ['2031:0000:130f:0000:0000:09c0:876a:130b']
},
{
title: '16进制颜色',
rule: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
examples: ['#f00', '#F90', '#000', '#fe9de8']
},
{
title: '微信号6至20位以字母开头字母数字减号下划线',
rule: /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/,
examples: ['github666', 'kd_-666']
},
{
title: '中国邮政编码',
rule: /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/,
examples: ['734500', '100101']
},
{
title: '只包含中文和数字',
rule: /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/,
examples: ['哈哈哈', '你好6啊']
},
{
title: '不能包含字母',
rule: /^[^A-Za-z]*$/,
examples: ['你好6啊', '@¥()']
}
];

View File

@ -1,8 +0,0 @@
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')

View File

@ -1,5 +0,0 @@
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/any-rule/'
: '/'
}

File diff suppressed because it is too large Load Diff

1
rules.json Normal file

File diff suppressed because one or more lines are too long

109
src/anyrule.ts Normal file
View File

@ -0,0 +1,109 @@
import { ExtensionContext, CompletionItem, CompletionItemKind, languages, Disposable, workspace, window, commands, TextDocument, Position, Range, Selection } from "vscode";
import { generateFilterString, getRulesByText } from "./utils";
import { IRule } from "./interface";
import { loadRules } from './loader';
export class AnyRule {
context: ExtensionContext;
disposable: Disposable | null = null;
rules: IRule[] | null = null;
constructor(context: ExtensionContext) {
this.context = context;
loadRules(context.extensionPath).then(rules => {
this.rules = rules;
this.load();
});
}
public load() {
let currentRules: IRule[] = [];
const configuration = workspace.getConfiguration();
let START_IDENTIFIER: string = configuration.get('anyRule.triggerString') || 'zz';
const setting: string = configuration.get('anyRule.supportedLanguages') || 'javascript,typescirpt' as string;
const supportedLanguages = setting.split(',');
this.commandRegisters(START_IDENTIFIER);
this.disposable = languages.registerCompletionItemProvider(supportedLanguages, {
provideCompletionItems: (document, position, token, context) => {
const line = document.lineAt(position);
const lineText = line.text.substring(0, position.character);
if (new RegExp(`${START_IDENTIFIER}\.`, 'g').test(lineText)) {
currentRules = getRulesByText(START_IDENTIFIER, this.rules || [], lineText);
return currentRules.map(rule => {
const item = new CompletionItem(rule.title, rule.regex ? CompletionItemKind.Field : CompletionItemKind.Folder);
// @ts-ignore
item.rule = rule;
// item.commitCharacters = ['.'];
item.filterText = generateFilterString(rule);
item.documentation = rule.regex ? `${rule.title}\n${rule.examples ? '\n示例\n' + rule.examples.join('\n') : ''}` : undefined;
item.command = {
title: '插入正则',
command: 'functions.insertRegex',
arguments: [document, position, rule]
};
return item;
});
}
},
resolveCompletionItem: (item: CompletionItem) => {
// @ts-ignore
const rule: IRule = item.rule;
if (rule.regex) {
return null;
} else {
item.insertText = item.label + '.';
return item;
}
},
}, '.');
this.context.subscriptions.push(this.disposable);
}
public reload() {
if (this.disposable) {
this.disposable.dispose();
}
this.load();
}
public update() {
loadRules(this.context.extensionPath, true).then(rules => {
this.rules = rules;
this.reload();
window.showInformationMessage('正则库已更新');
});
}
private commandRegisters(START_IDENTIFIER: string) {
commands.getCommands().then((commandList) => {
if (commandList.indexOf('functions.insertRegex') !== -1) {
return;
}
commands.registerCommand('functions.insertRegex', (document: TextDocument, position: Position, rule: IRule) => {
if (rule.regex) {
const editor = window.activeTextEditor;
editor?.edit(editBuilder => {
const line = document.lineAt(position);
const start = line.text.indexOf(START_IDENTIFIER);
if (start === -1) {
return;
}
if (rule.regex) {
editBuilder.replace(
new Range(new Position(line.lineNumber, start),
new Position(line.lineNumber, line.text.length)),
String(rule.regex)
);
// TODO 处理输入文本后选中字符串的问题
const end = new Position(line.lineNumber, line.text.length + String(rule.regex).length);
editor.selection = new Selection(end, end);
}
});
} else {
commands.executeCommand('editor.action.triggerSuggest');
}
});
});
}
}

0
src/constant.ts Normal file
View File

View File

@ -1,10 +1,16 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
const RULES = require('../packages/www/src/RULES.js');
import {
window, workspace, commands,
ExtensionContext, ConfigurationChangeEvent
} from 'vscode';
import { IRule } from './interface';
import { AnyRule } from './anyrule';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
export function activate(context: ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "any-rule" is now active!');
@ -12,44 +18,45 @@ export function activate(context: vscode.ExtensionContext) {
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
// let disposable = vscode.commands.registerCommand('extension.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// // The code you place here will be executed every time your command is executed
// Display a message box to the user
// vscode.window.showInformationMessage('Hello World123!');
// // Display a message box to the user
// vscode.window.showInformationMessage('Hello World!');
// });
// context.subscriptions.push(disposable);
const anyRule = new AnyRule(context);
RULES.forEach(({ title, rule }: { title: string, rule: RegExp, example: string }, index: string) => {
let disposable = vscode.commands.registerCommand(`extension.rule${index}`, () => {
// The code you place here will be executed every time your command is executed
const editor = vscode.window.activeTextEditor;
if (editor) {
const { selections } = editor;
editor.edit(editBuilder => {
selections.forEach(selection => {
const { start, end } = selection;
const range = new vscode.Range(start, end);
editBuilder.replace(range, String(rule));
});
});
// Display a message box to the user
vscode.window.showInformationMessage(`已插入正则: ${title}`);
} else {
vscode.window.showWarningMessage('any-rule: 只有在编辑文本的时候才可以使用!');
}
});
context.subscriptions.push(disposable);
workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
anyRule.reload();
});
commands.registerCommand('extension.update', () => {
anyRule.update();
});
commands.registerCommand('extension.reload', () => {
anyRule.reload();
window.showInformationMessage('重新加载插件成功');
});
commands.registerCommand('extension.support', () => {
const currentLanguage = window.activeTextEditor?.document.languageId;
if (currentLanguage) {
try {
const configuration = workspace.getConfiguration();
const setting: string = configuration.get('anyRule.supportedLanguages') || 'javascript,typescirpt' as string;
const supportedLanguages = setting.split(',');
const set = new Set(supportedLanguages);
set.add(currentLanguage);
console.log(Array.from(set).join(','));
configuration.update('anyRule.supportedLanguages', Array.from(set).join(',')).then(() => {
anyRule.reload();
});
window.showInformationMessage('更新关联语言成功');
} catch(e) {
window.showInformationMessage('更新关联语言失败');
}
}
});
}
// this method is called when your extension is deactivated
export function deactivate() {
vscode.window.showWarningMessage('any-rule: 已关闭!');
}
export function deactivate() { }

7
src/interface.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
export interface IRule {
title: string;
keywords?: string[];
regex?: RegExp | string;
rules?: IRule[];
examples?: string[];
}

45
src/loader.ts Normal file
View File

@ -0,0 +1,45 @@
import { workspace, Uri } from 'vscode';
import axios from 'axios';
import { IRule } from './interface';
async function loadRulesFromFile(path: Uri): Promise<IRule[] | null> {
try {
const json = await workspace.fs.readFile(path);
return JSON.parse(json.toString()) as IRule[];
} catch(e) {
return null;
}
}
async function loadRulesFromWeb(): Promise<IRule[]> {
const dataSources = [
'https://raw.githubusercontent.com/any86/any-rule/feature/vscode-refactor/rules.json'
];
let rules: IRule[] = [];
for (const source of dataSources) {
try {
const response = await axios.get(source);
const body = response.data;
rules = body as IRule[];
} catch(e) {
console.log(e);
continue;
}
}
return rules;
}
export async function loadRules (extensionPath: string, force: boolean = false): Promise<IRule[]> {
const fileUri = Uri.parse(`file://${extensionPath}/rules.json`);
let rules: IRule[] | null = null;
if (!force) {
rules = await loadRulesFromFile(fileUri);
}
if (!rules) {
rules = await loadRulesFromWeb();
await workspace.fs.writeFile(fileUri, Buffer.from(JSON.stringify(rules)));
}
return rules;
}

View File

@ -1,23 +0,0 @@
import * as path from 'path';
import { runTests } from 'vscode-test';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './suite/index');
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error('Failed to run tests');
process.exit(1);
}
}
main();

View File

@ -1,18 +0,0 @@
import * as assert from 'assert';
import { before } from 'mocha';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../extension';
suite('Extension Test Suite', () => {
before(() => {
vscode.window.showInformationMessage('Start all tests.');
});
test('Sample test', () => {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});

View File

@ -1,37 +0,0 @@
import * as path from 'path';
import * as Mocha from 'mocha';
import * as glob from 'glob';
export function run(): Promise<void> {
// Create the mocha test
const mocha = new Mocha({
ui: 'tdd',
});
mocha.useColors(true);
const testsRoot = path.resolve(__dirname, '..');
return new Promise((c, e) => {
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
if (err) {
return e(err);
}
// Add files to the test suite
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
try {
// Run the mocha test
mocha.run(failures => {
if (failures > 0) {
e(new Error(`${failures} tests failed.`));
} else {
c();
}
});
} catch (err) {
e(err);
}
});
});
}

95
src/utils.ts Normal file
View File

@ -0,0 +1,95 @@
import { IRule } from './interface';
import * as pinyin from 'pinyin';
function preprocessText(START_IDENTIFIER: string, text: string): string[] | null {
const start = text.indexOf(START_IDENTIFIER);
if (start === -1) {
return null;
}
const pathString = text.substring(start, text.length);
const pathArray = pathString.split('.');
return pathArray;
}
/**
*
* @param text
*/
export function getRulesByText(START_IDENTIFIER: string, rules: IRule[], text: string): IRule[] {
const pathArray = preprocessText(START_IDENTIFIER, text);
if (!pathArray) {
return [];
}
let currentRules: IRule[] = [];
let targetRules = rules;
for (const path of pathArray) {
if (path === START_IDENTIFIER) {
currentRules = rules;
} else if (path === '') {
console.log('path');
break;
} else {
const searchRule = targetRules.find(rule => rule.title === path);
if (!searchRule) {
return [];
}
if (searchRule.regex) {
return [];
}
currentRules = searchRule.rules || [];
targetRules = currentRules;
}
}
return currentRules;
}
export function getRuleByText(START_IDENTIFIER: string, rules: IRule[], text: string): IRule | null {
const pathArray = preprocessText(START_IDENTIFIER, text);
if (!pathArray) {
return null;
}
let targetRules = rules;
let searchRule: IRule | undefined;
for (const path of pathArray) {
if (path === START_IDENTIFIER) {
continue;
}
searchRule = targetRules.find(rule => rule.title === path);
if (!searchRule) {
return null;
}
if (searchRule.regex) {
break;
} else {
targetRules = searchRule.rules || [];
}
}
return searchRule || null;
}
export function generateFilterString(rule: IRule) {
let filterString = '';
filterString += rule.title;
if (/.*[\u4e00-\u9fa5]+.*$/.test(rule.title)) {
filterString += ' ' + pinyin(rule.title, {
style: pinyin.STYLE_NORMAL
}).join('');
filterString += ' ' + pinyin(rule.title, {
style: pinyin.STYLE_FIRST_LETTER
}).join('');
}
if (rule.keywords) {
filterString += ' ' + rule.keywords.join(' ');
}
return filterString;
}

753
yarn.lock

File diff suppressed because it is too large Load Diff