🆙 Add cms i using 🆙

This commit is contained in:
Remco
2025-11-25 22:42:56 +01:00
parent 94704e0925
commit d44196149e
35591 changed files with 3601123 additions and 0 deletions
@@ -0,0 +1,106 @@
# Changelog
## [0.4.3](https://github.com/shufo/html-attribute-sorter/compare/v0.4.2...v0.4.3) (2022-12-25)
### Miscellaneous
* **deps:** update dependency esbuild to ^0.15.0 ([86bf865](https://github.com/shufo/html-attribute-sorter/commit/86bf865d1cfcf460c59a98417779b315ccf232b9))
* **deps:** update pozil/auto-assign-issue action to v1.10.0 ([577a966](https://github.com/shufo/html-attribute-sorter/commit/577a96642b452783edb41d5cad85c5ed351c5dfb))
* **deps:** update pozil/auto-assign-issue action to v1.11.0 ([635d4ff](https://github.com/shufo/html-attribute-sorter/commit/635d4ffd81b336994095282aea2009913578c581))
* **deps:** update thollander/actions-comment-pull-request action to v2 ([bb16552](https://github.com/shufo/html-attribute-sorter/commit/bb16552037307d710bb8764ec72c6aad477b2705))
### Fixes
* 🐛 fix: attribute doubles when v-else-if exists ([441c815](https://github.com/shufo/html-attribute-sorter/commit/441c8150697487e0f9de918d9a10a44ffca3d00b))
## [0.4.2](https://github.com/shufo/html-attribute-sorter/compare/v0.4.1...v0.4.2) (2022-08-09)
### Fixes
* 🐛 unexpected reordering in eattributes with no space ([b83fe6d](https://github.com/shufo/html-attribute-sorter/commit/b83fe6daaf16f6cc91ecb613aeca4420be997242))
## [0.4.1](https://github.com/shufo/html-attribute-sorter/compare/v0.4.0...v0.4.1) (2022-08-08)
### Fixes
* 🐛 does not capture when quotations are not present ([2ca7ec8](https://github.com/shufo/html-attribute-sorter/commit/2ca7ec8d53db113aa6e58a6d45e4017fd2ab0e05))
* 🐛 not captured if there is a space around equal ([0c7c52e](https://github.com/shufo/html-attribute-sorter/commit/0c7c52ec78779c40c2e858ae29727b1760dbd4ff))
## [0.4.0](https://github.com/shufo/html-attribute-sorter/compare/v0.3.2...v0.4.0) (2022-08-07)
### Features
* 🎸 add custom order strategy ([64e5639](https://github.com/shufo/html-attribute-sorter/commit/64e563912ad71a1a06c4551bab5c8930d9335942))
## [0.3.2](https://github.com/shufo/html-attribute-sorter/compare/v0.3.1...v0.3.2) (2022-08-06)
### Fixes
* 🐛 do not sort remaining attributes other than spec ([d46daa1](https://github.com/shufo/html-attribute-sorter/commit/d46daa19ef44f0dc7e690d8d7ea4583e32a44b17))
### Miscellaneous
* **deps:** update peter-evans/commit-comment action to v2 ([5a00b31](https://github.com/shufo/html-attribute-sorter/commit/5a00b31fe87d6d6fe7fc2829e4a3b7187e246a17))
## [0.3.1](https://github.com/shufo/html-attribute-sorter/compare/v0.3.0...v0.3.1) (2022-08-06)
### Fixes
* 🐛 change parameter value from code_guide to code-guide ([f2b49ad](https://github.com/shufo/html-attribute-sorter/commit/f2b49ad5b320da206f239d7a0a86f8d6b8a06650))
### Miscellaneous
* **deps:** update googlecloudplatform/release-please-action action to v3 ([e0a6b9a](https://github.com/shufo/html-attribute-sorter/commit/e0a6b9a8b333add204c7b5530598344cd75e997c))
* **deps:** update jest monorepo to v28 ([8d1a01b](https://github.com/shufo/html-attribute-sorter/commit/8d1a01b99795df41bfc935156c346dd0f1721721))
## [0.3.0](https://www.github.com/shufo/html-attribute-sorter/compare/v0.2.1...v0.3.0) (2022-08-06)
### Features
* 🎸 add vuejs sorting strategy ([3d4219f](https://www.github.com/shufo/html-attribute-sorter/commit/3d4219f9ae26b83714b4ac43ad6c24eed7b8e412))
### Fixes
* 🐛 unexpected custom directive position for vuejs order ([c40d0ad](https://www.github.com/shufo/html-attribute-sorter/commit/c40d0ad1c9ffe9d21886406727fd2edd7e5e2c68))
### [0.2.1](https://www.github.com/shufo/html-attribute-sorter/compare/v0.2.0...v0.2.1) (2022-08-06)
### Fixes
* 🐛 regex does not match specific tag ([6d94431](https://www.github.com/shufo/html-attribute-sorter/commit/6d944314fb2c68950527ed8a7992c15e98b0dfc5))
### Miscellaneous
* **deps:** update actions/cache action to v3 ([094a395](https://www.github.com/shufo/html-attribute-sorter/commit/094a395bcdf5137efed4971449aac3973c688fb0))
* **deps:** update actions/checkout action to v3 ([b109c93](https://www.github.com/shufo/html-attribute-sorter/commit/b109c93259e443f8bb916418b3488f5096d73c86))
* **deps:** update actions/setup-node action to v3 ([0ca780e](https://www.github.com/shufo/html-attribute-sorter/commit/0ca780ecd9c04d7f78673d95f01d6d49c08ae275))
* **deps:** update codecov/codecov-action action to v3 ([38b87de](https://www.github.com/shufo/html-attribute-sorter/commit/38b87deb8630302fedbeb5e384cdf22b3a97e730))
## [0.2.0](https://www.github.com/shufo/html-attribute-sorter/compare/v0.1.0...v0.2.0) (2022-08-05)
### Features
* 🎸 change name of option parameter ([5b5951b](https://www.github.com/shufo/html-attribute-sorter/commit/5b5951bb3b0c8e761fd5de2a7e898e6cc480711b))
## 0.1.0 (2022-08-05)
### Miscellaneous
* 🤖 require min node engine version as 12.0.0 ([6526bbc](https://www.github.com/shufo/html-attribute-sorter/commit/6526bbc55baa16c2b908d59c904ffa3c8346e012))
* **deps:** update pozil/auto-assign-issue action to v1.9.0 ([fc1aa07](https://www.github.com/shufo/html-attribute-sorter/commit/fc1aa07fe5bcf536c6be3caa02f37d1ebc8beee1))
* Initialized ([5fb24cf](https://www.github.com/shufo/html-attribute-sorter/commit/5fb24cfdc1ccf8b46a938fe3018b3fda02c2893c))
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Shuhei Hayashibara
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.
@@ -0,0 +1,121 @@
[![npm](https://img.shields.io/npm/v/html-attribute-sorter)](https://www.npmjs.com/package/html-attribute-sorter)
[![CI](https://github.com/shufo/html-attribute-sorter/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/shufo/html-attribute-sorter/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/shufo/html-attribute-sorter/branch/main/graph/badge.svg?token=U7YzstHupS)](https://codecov.io/gh/shufo/html-attribute-sorter)
# html-attribute-sorter
An html attribute sorter.
You can sort attributes by alphabetical, [code guide](https://codeguide.co/#attribute-order), [vue/attributes-order](https://eslint.vuejs.org/rules/attributes-order.html), [idiomatic](https://github.com/necolas/idiomatic-html#attribute-order) or any custom order using regex.
## Installation
```bash
$ npm install html-attribute-sorter
# yarn
$ yarn add html-attribute-sorter
```
## Usage
```typescript
const { sortAttributes } = require("html-attribute-sorter");
// pass html tags that includes attributes
// default: code guide order
const sorted = sortAttributes(`<img src="foo" class="img b-30" id="img_10">`);
console.log(sorted);
// => <img class="img b-30" id="img_10" src="foo">
// alphabetical order
const sorted = sortAttributes(
`<img src="foo" alt="title" class="img b-30" id="img_10">`,
{
order: "alphabetical",
}
);
console.log(sorted);
// => <img alt="title" class="img b-30" id="img_10" src="foo">
// idiomatic order
const sorted = sortAttributes(
`<img src="foo" alt="title" class="img b-30" id="img_10">`,
{
order: "idiomatic",
}
);
console.log(sorted);
// => <img class="img b-30" id="img_10" alt="title" src="foo">
// code guide order
const sorted = sortAttributes(
`<img src="foo" alt="title" class="img b-30" id="img_10">`,
{
order: "code-guide",
}
);
console.log(sorted);
// => <img class="img b-30" id="img_10" src="foo">
// custom order
const sorted = sortAttributes(
`<img src="foo" alt="title" class="img b-30" id="img_10">`,
{
order: "custom",
customRegexes: ["id", "class", "sr.+", "alt"], // you can use regex for attritube names
}
);
console.log(sorted);
// => <img id="img_10" class="img b-30" src="foo" alt="title" >
```
## API
### functions
#### sortAttributes(body: string, options: ISortOption)
`body`: html tag string e.g. `<img src="..." alt="title" class="pg-10">`
### Interfaces
#### ISortOption
```typescript
export interface ISortOption {
order: string;
customRegexes?: string[];
}
```
| key | value | required | default |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------ |
| order | An order to sort attributes. You can specify `alphabetical`, `code-guide`, `idiomatic`, `vuejs` or `custom`. | yes | `code-guide` |
| customRegexes | When `order` is specified to `custom`, html attributes set here will be used as order. You can use regex for attribute names. e.g. `["data-.+", "class", "src"]`. | no | `[]` |
## Testing
```bash
$ yarn install
$ yarn run test
```
## Benchmarking
```bash
$ yarn run benchmark
```
![image](https://user-images.githubusercontent.com/1641039/182972283-3d7e48bf-3f8b-40b1-92c0-334a1e2fba3e.png)
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## LICENSE
MIT
@@ -0,0 +1,2 @@
"use strict";var h=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var I=(r,t)=>{for(var e in t)h(r,e,{get:t[e],enumerable:!0})},O=(r,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of v(t))!x.call(r,s)&&s!==e&&h(r,s,{get:()=>t[s],enumerable:!(o=E(t,s))||o.enumerable});return r};var R=r=>O(h({},"__esModule",{value:!0}),r);var C={};I(C,{sortAttributes:()=>y});module.exports=R(C);var g=class{constructor(t){this.strategy=t}setStrategy(t){this.strategy=t}sort(t){return this.strategy.sort(t)}};var p=class{sort(t){return t.sort()}};var d=class{constructor(){this.orderedAttrsRegex=["class","id","name","data-.+","ng-.+","src","for","type","href","value","values","title","alt","role","aria-.+","tabindex","style"]}sort(t){let e=[];this.orderedAttrsRegex.forEach(s=>{t.forEach(i=>{new RegExp(`^${s}`).test(i)&&e.push(i)})});let o=t.filter(s=>e.indexOf(s)===-1);return e.concat(o)}};var l=class{constructor(t){this.orderedAttrsRegex=[];if(t.customRegexes===void 0)throw new Error("customRegexes is empty. You must specify custom order to use custom strategy");this.orderedAttrsRegex=t.customRegexes}sort(t){let e=[];this.orderedAttrsRegex.forEach(s=>{t.forEach(i=>{new RegExp(`^${s}`).test(i)&&e.push(i)})});let o=t.filter(s=>e.indexOf(s)===-1);return e.concat(o)}};var f=class{constructor(){this.orderedAttrsRegex=["class","id","data-.+"]}sort(t){let e=[];this.orderedAttrsRegex.forEach(s=>{t.forEach(i=>{new RegExp(`^${s}`).test(i)&&e.push(i)})});let o=t.filter(s=>e.indexOf(s)===-1);return e.concat(o)}};var u=class{constructor(){this.DEFINITION=["is","v-is"];this.LIST_RENDERING=["v-for"];this.CONDITIONALS=["v-if","v-else-if","v-else","v-show","v-cloak"];this.RENDER_MODIFIERS=["v-once","v-pre"];this.GLOBAL=["id"];this.UNIQUE=["ref","key"];this.SLOT=["v-slot","slot"];this.TWO_WAY_BINDING=["v-model"];this.OTHER_DIRECTIVES=/v-[-:\w\d]+/g;this.EVENTS=["@click","v-on="];this.CONTENT=["v-text","v-html"];this.headingOrderedAttrsRegex=[...this.DEFINITION,...this.LIST_RENDERING,...this.CONDITIONALS,...this.RENDER_MODIFIERS,...this.GLOBAL,...this.UNIQUE,...this.SLOT,...this.TWO_WAY_BINDING];this.tailOrderedAttrsRegex=[...this.EVENTS,...this.CONTENT]}sort(t){let e=[],o=[];this.headingOrderedAttrsRegex.forEach(n=>{t.forEach(a=>{new RegExp(`^${n}(_attrs_\\d+___)?$`,"gm").test(a)&&e.push(a)})}),this.tailOrderedAttrsRegex.forEach(n=>{t.forEach(a=>{new RegExp(`^${n}`).test(a)&&o.push(a)})});let s=t.filter(n=>e.indexOf(n)===-1).filter(n=>o.indexOf(n)===-1),i=s.filter(n=>this.OTHER_DIRECTIVES.test(n)),c=s.filter(n=>i.indexOf(n)===-1);return e.concat(i).concat(c).concat(o)}};var S=[],_=[];function y(r,t={order:"code-guide"}){let e=r.replace(/<(?!\/)[-:.\w\d@]+\s(?:"[^"]*"|'[^']*'|[^"'])*?>/g,o=>N(o));return D(e,t)}function N(r){let t=S.push(r)-1;return w(t.toString())}function A(r,t){let e=_.push(t)-1;return T(r,e.toString())}function w(r){return"___sort_tags_#___".replace("#",r)}function T(r,t){return`${r}_attrs_#___`.replace("#",t)}function D(r,t){return r.replace(/___sort_tags_(\d+)___/g,(e,o)=>{let i=S[o].replace(/([-:.\w\d]+)\s*=\s*("[^"]*"|'[^']*'|[^"'>\s]+)/g,(a,m)=>A(m,a));return L(i,t).replace(/[-:.\w\d]+?_attrs_(\d+)___/g,(a,m)=>_[m])})}function L(r,t){let e=b(t),o=new g(e);return r.replace(/(?<=<[-:.\w\d]+\s)[^>]*?(?=\/?>)/g,s=>{let c=s.split(/\s/).filter(a=>a.length>0);return o.sort(c).join(" ")})}function b(r){switch(r.order){case"alphabetical":return new p;case"code-guide":return new d;case"idiomatic":return new f;case"vuejs":return new u;case"custom":return new l(r)}throw new Error("You can specify only [alphabetical|code-guide|idiomatic|vuejs] for sorting order")}0&&(module.exports={sortAttributes});
//# sourceMappingURL=main.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import { ISortOption } from "./options";
export declare function sortAttributes(html: string, options?: ISortOption): string;
@@ -0,0 +1,5 @@
export declare type Strategy = "alphabetical" | "code-guide" | "idiomatic" | "vuejs" | "custom";
export interface ISortOption {
order: Strategy;
customRegexes?: string[];
}
@@ -0,0 +1,9 @@
export interface SortStrategy {
sort(attributes: string[]): string[];
}
export declare class Sorter {
private strategy;
constructor(strategy: SortStrategy);
setStrategy(strategy: SortStrategy): void;
sort(attributes: string[]): string[];
}
@@ -0,0 +1,4 @@
import { SortStrategy } from "../sorter";
export declare class AlphabeticalStrategy implements SortStrategy {
sort(attributes: string[]): string[];
}
@@ -0,0 +1,9 @@
import { SortStrategy } from "../sorter";
/**
* Code guide strategy
* see: https://codeguide.co/
*/
export declare class CodeGuideStrategy implements SortStrategy {
private orderedAttrsRegex;
sort(attributes: string[]): string[];
}
@@ -0,0 +1,10 @@
import { ISortOption } from "../options";
import { SortStrategy } from "../sorter";
/**
* Custom order strategy
*/
export declare class CustomStrategy implements SortStrategy {
private orderedAttrsRegex;
constructor(options: ISortOption);
sort(attributes: string[]): string[];
}
@@ -0,0 +1,9 @@
import { SortStrategy } from "../sorter";
/**
* Idiomatic strategy
* see: https://github.com/necolas/idiomatic-html#attribute-order
*/
export declare class IdiomaticStrategy implements SortStrategy {
private orderedAttrsRegex;
sort(attributes: string[]): string[];
}
@@ -0,0 +1,21 @@
import { SortStrategy } from "../sorter";
/**
* vuejs order
* see: https://eslint.vuejs.org/rules/attributes-order.html
*/
export declare class VuejsStrategy implements SortStrategy {
private DEFINITION;
private LIST_RENDERING;
private CONDITIONALS;
private RENDER_MODIFIERS;
private GLOBAL;
private UNIQUE;
private SLOT;
private TWO_WAY_BINDING;
private OTHER_DIRECTIVES;
private EVENTS;
private CONTENT;
private headingOrderedAttrsRegex;
private tailOrderedAttrsRegex;
sort(attributes: string[]): string[];
}
@@ -0,0 +1,65 @@
{
"name": "html-attribute-sorter",
"version": "0.4.3",
"description": "An html attribute sorter",
"main": "dist/main.js",
"types": "./dist/types/main.d.ts",
"scripts": {
"build": "cross-env NODE_ENV=production node esbuild.ts",
"watch": "node esbuild.ts",
"test": "yarn build && node --experimental-vm-modules ./node_modules/.bin/jest",
"lint": "eslint . --ext .ts",
"fix": "eslint . --ext .ts --fix",
"prepublish": "tsc src/main.ts --declaration --emitDeclarationOnly --outDir ./dist/types || true",
"format": "yarn run format:ts",
"format:ts": "prettier {src,__tests__}/**/*.{ts,json} -w",
"format:check": "prettier {src,__tests__}/**/*.{ts,json} -c",
"prepare": "husky install",
"benchmark": "yarn run build && node benchmark/run.js"
},
"author": "Shuhei Hayashibara",
"license": "MIT",
"devDependencies": {
"@types/jest": "^28.0.0",
"@typescript-eslint/eslint-plugin": "^5.12.1",
"@typescript-eslint/parser": "^5.12.1",
"benny": "^3.7.1",
"codecov": "^3.8.3",
"cross-env": "^7.0.3",
"esbuild": "^0.15.0",
"esbuild-node-externals": "^1.4.1",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.4.0",
"husky": "^7.0.4",
"jest": "^28.0.0",
"lint-staged": "^12.3.4",
"prettier": "^2.5.1",
"prettier-plugin-tailwindcss": "^0.1.7",
"ts-jest": "^28.0.0",
"ts-node": "^10.5.0",
"typescript": "^4.5.5"
},
"dependencies": {},
"files": [
"dist",
"src",
"CHANGELOG.md"
],
"repository": {
"type": "git",
"url": "https://github.com/shufo/html-attribute-sorter.git"
},
"publishConfig": {
"access": "public"
},
"lint-staged": {
"*.ts": "yarn run fix && yarn run format"
},
"keywords": [
"html",
"sorter"
],
"engines": {
"node": ">= 12.0.0"
}
}
@@ -0,0 +1,95 @@
import { ISortOption, Strategy } from "./options";
import { Sorter } from "./sorter";
import { AlphabeticalStrategy } from "./strategy/alphabetical";
import { CodeGuideStrategy } from "./strategy/code-guide";
import { CustomStrategy } from "./strategy/custom";
import { IdiomaticStrategy } from "./strategy/idiomatic";
import { VuejsStrategy } from "./strategy/vuejs";
const maps: Array<string> = [];
const attrs: Array<string> = [];
export function sortAttributes(
html: string,
options: ISortOption = { order: "code-guide" }
) {
const replaced = html.replace(
// capture html tags
/<(?!\/)[-:.\w\d@]+\s(?:"[^"]*"|'[^']*'|[^"'])*?>/g,
(match: string) => {
return storeTags(match);
}
);
return restoreAttributes(replaced, options);
}
function storeTags(value: string) {
const index = maps.push(value) - 1;
return getTagPlaceholder(index.toString());
}
function storeAttributes(name: string, value: string) {
const index = attrs.push(value) - 1;
return getAttributePlaceholder(name, index.toString());
}
function getTagPlaceholder(index: string) {
return `___sort_tags_#___`.replace("#", index);
}
function getAttributePlaceholder(name, index: string) {
return `${name}_attrs_#___`.replace("#", index);
}
function restoreAttributes(content: string, options: ISortOption) {
return content.replace(
/___sort_tags_(\d+)___/g,
(_match: string, p1: string) => {
const matched = maps[p1];
const replaced = matched.replace(
// capture attributes
/([-:.\w\d]+)\s*=\s*("[^"]*"|'[^']*'|[^"'>\s]+)/g,
(match: string, p1: string) => storeAttributes(p1, match)
);
const sorted = _sortAttributes(replaced, options);
const restored = sorted.replace(
/[-:.\w\d]+?_attrs_(\d+)___/g,
(_match, p1) => attrs[p1]
);
return restored;
}
);
}
function _sortAttributes(content: string, options: ISortOption): string {
const strategy = getSortStrategy(options);
const sorter = new Sorter(strategy);
return content.replace(/(?<=<[-:.\w\d]+\s)[^>]*?(?=\/?>)/g, (match) => {
const splitted = match.split(/\s/);
const filtered = splitted.filter((x) => x.length > 0);
const sorted = sorter.sort(filtered);
return sorted.join(" ");
});
}
function getSortStrategy(options: ISortOption) {
switch (options.order) {
case "alphabetical":
return new AlphabeticalStrategy();
case "code-guide":
return new CodeGuideStrategy();
case "idiomatic":
return new IdiomaticStrategy();
case "vuejs":
return new VuejsStrategy();
case "custom":
return new CustomStrategy(options);
}
throw new Error(
`You can specify only [alphabetical|code-guide|idiomatic|vuejs] for sorting order`
);
}
@@ -0,0 +1,11 @@
export type Strategy =
| "alphabetical"
| "code-guide"
| "idiomatic"
| "vuejs"
| "custom";
export interface ISortOption {
order: Strategy;
customRegexes?: string[];
}
@@ -0,0 +1,19 @@
export interface SortStrategy {
sort(attributes: string[]): string[];
}
export class Sorter {
private strategy: SortStrategy;
constructor(strategy: SortStrategy) {
this.strategy = strategy;
}
public setStrategy(strategy: SortStrategy) {
this.strategy = strategy;
}
public sort(attributes: string[]): string[] {
return this.strategy.sort(attributes);
}
}
@@ -0,0 +1,7 @@
import { SortStrategy } from "../sorter";
export class AlphabeticalStrategy implements SortStrategy {
sort(attributes: string[]): string[] {
return attributes.sort();
}
}
@@ -0,0 +1,45 @@
import { SortStrategy } from "../sorter";
/**
* Code guide strategy
* see: https://codeguide.co/
*/
export class CodeGuideStrategy implements SortStrategy {
private orderedAttrsRegex = [
"class",
"id",
"name",
"data-.+",
"ng-.+",
"src",
"for",
"type",
"href",
"value",
"values",
"title",
"alt",
"role",
"aria-.+",
"tabindex",
"style",
];
sort(attributes: string[]): string[] {
const sorted: string[] = [];
this.orderedAttrsRegex.forEach((regex) => {
attributes.forEach((attr) => {
if (new RegExp(`^${regex}`).test(attr)) {
sorted.push(attr);
}
});
});
const remainings = attributes.filter(
(attr) => sorted.indexOf(attr) === -1
);
return sorted.concat(remainings);
}
}
@@ -0,0 +1,37 @@
import { ISortOption } from "../options";
import { SortStrategy } from "../sorter";
/**
* Custom order strategy
*/
export class CustomStrategy implements SortStrategy {
private orderedAttrsRegex: string[] = [];
public constructor(options: ISortOption) {
if (options.customRegexes === undefined) {
throw new Error(
"customRegexes is empty. You must specify custom order to use custom strategy"
);
}
this.orderedAttrsRegex = options.customRegexes;
}
sort(attributes: string[]): string[] {
const sorted: string[] = [];
this.orderedAttrsRegex.forEach((regex) => {
attributes.forEach((attr) => {
if (new RegExp(`^${regex}`).test(attr)) {
sorted.push(attr);
}
});
});
const remainings = attributes.filter(
(attr) => sorted.indexOf(attr) === -1
);
return sorted.concat(remainings);
}
}
@@ -0,0 +1,27 @@
import { SortStrategy } from "../sorter";
/**
* Idiomatic strategy
* see: https://github.com/necolas/idiomatic-html#attribute-order
*/
export class IdiomaticStrategy implements SortStrategy {
private orderedAttrsRegex = ["class", "id", "data-.+"];
sort(attributes: string[]): string[] {
const sorted: string[] = [];
this.orderedAttrsRegex.forEach((regex) => {
attributes.forEach((attr) => {
if (new RegExp(`^${regex}`).test(attr)) {
sorted.push(attr);
}
});
});
const remainings = attributes.filter(
(attr) => sorted.indexOf(attr) === -1
);
return sorted.concat(remainings);
}
}
@@ -0,0 +1,72 @@
import { SortStrategy } from "../sorter";
/**
* vuejs order
* see: https://eslint.vuejs.org/rules/attributes-order.html
*/
export class VuejsStrategy implements SortStrategy {
private DEFINITION = ["is", "v-is"];
private LIST_RENDERING = ["v-for"];
private CONDITIONALS = ["v-if", "v-else-if", "v-else", "v-show", "v-cloak"];
private RENDER_MODIFIERS = ["v-once", "v-pre"];
private GLOBAL = ["id"];
private UNIQUE = ["ref", "key"];
private SLOT = ["v-slot", "slot"];
private TWO_WAY_BINDING = ["v-model"];
private OTHER_DIRECTIVES = /v-[-:\w\d]+/g;
private EVENTS = ["@click", "v-on="];
private CONTENT = ["v-text", "v-html"];
private headingOrderedAttrsRegex = [
...this.DEFINITION,
...this.LIST_RENDERING,
...this.CONDITIONALS,
...this.RENDER_MODIFIERS,
...this.GLOBAL,
...this.UNIQUE,
...this.SLOT,
...this.TWO_WAY_BINDING,
];
private tailOrderedAttrsRegex = [...this.EVENTS, ...this.CONTENT];
sort(attributes: string[]): string[] {
const head: string[] = [];
const tail: string[] = [];
this.headingOrderedAttrsRegex.forEach((regex) => {
attributes.forEach((attr) => {
if (
new RegExp(`^${regex}(_attrs_\\d+___)?$`, "gm").test(attr)
) {
head.push(attr);
}
});
});
this.tailOrderedAttrsRegex.forEach((regex) => {
attributes.forEach((attr) => {
if (new RegExp(`^${regex}`).test(attr)) {
tail.push(attr);
}
});
});
const remainings = attributes
.filter((attr) => head.indexOf(attr) === -1)
.filter((attr) => tail.indexOf(attr) === -1);
const customDirectives: string[] = remainings.filter((attr) =>
this.OTHER_DIRECTIVES.test(attr)
);
const remainingsWithoutCustomDirective = remainings.filter(
(attr) => customDirectives.indexOf(attr) === -1
);
return head
.concat(customDirectives)
.concat(remainingsWithoutCustomDirective)
.concat(tail);
}
}