prettier-plugin-bootstrap 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,13 @@ A [Prettier](https://prettier.io/) plugin that automatically sorts Bootstrap CSS
9
9
 
10
10
  Works with **HTML**, **JSX/TSX**, **Vue**, **Angular**, **Svelte**, and **Astro** templates.
11
11
 
12
+ ## Why?
13
+
14
+ - **Consistency** — Every file in your project uses the same class order, regardless of who wrote it.
15
+ - **Smaller diffs** — Sorted classes eliminate noisy reordering in pull requests.
16
+ - **Readability** — Classes follow Bootstrap's architecture (layout → components → utilities), making it easier to scan what an element does.
17
+ - **Zero config** — Just add the plugin and format. No ESLint rules to configure, no manual sorting.
18
+
12
19
  ## Installation
13
20
 
14
21
  ```bash
@@ -63,21 +70,87 @@ Unknown classes are preserved in their original relative order and placed after
63
70
 
64
71
  ## Options
65
72
 
66
- | Option | Type | Default | Description |
67
- | --------------------- | ---------- | ------- | -------------------------------------------------------------------------- |
68
- | `bootstrapAttributes` | `string[]` | `[]` | Additional HTML attributes to sort (beyond `class` and `className`) |
69
- | `bootstrapFunctions` | `string[]` | `[]` | Function names whose arguments are class lists (e.g. `clsx`, `classNames`) |
73
+ | Option | Type | Default | Description |
74
+ | ----------------------------- | ---------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
75
+ | `bootstrapAttributes` | `string[]` | `[]` | Additional HTML attributes to sort (beyond `class` and `className`). Supports regex patterns (e.g. `/^data-class/`). |
76
+ | `bootstrapFunctions` | `string[]` | `[]` | Function names whose arguments are class lists (e.g. `clsx`, `classNames`) |
77
+ | `bootstrapPreserveWhitespace` | `boolean` | `false` | Preserve original whitespace between classes instead of normalizing to single spaces |
78
+ | `bootstrapPreserveDuplicates` | `boolean` | `true` | Keep duplicate class names. Set to `false` to remove duplicates |
79
+ | `bootstrapVersion` | `int` | `5` | Bootstrap version (for future version-specific sorting rules) |
70
80
 
71
81
  ### Example
72
82
 
73
83
  ```json
74
84
  {
75
85
  "plugins": ["prettier-plugin-bootstrap"],
76
- "bootstrapAttributes": ["ngClass", "v-bind:class"],
86
+ "bootstrapAttributes": ["ngClass", "v-bind:class", "/^data-class/"],
77
87
  "bootstrapFunctions": ["clsx", "cn", "classNames"]
78
88
  }
79
89
  ```
80
90
 
91
+ ### TypeScript Configuration
92
+
93
+ For type-safe configuration, use JSDoc annotations:
94
+
95
+ ```js
96
+ /** @type {import('prettier-plugin-bootstrap').BootstrapPluginOptions} */
97
+ const config = {
98
+ plugins: ['prettier-plugin-bootstrap'],
99
+ bootstrapAttributes: ['ngClass'],
100
+ bootstrapFunctions: ['clsx', 'cn'],
101
+ bootstrapPreserveDuplicates: false,
102
+ }
103
+
104
+ export default config
105
+ ```
106
+
107
+ ### Regex Attributes
108
+
109
+ You can use regex patterns in `bootstrapAttributes` to match dynamic attribute names:
110
+
111
+ ```json
112
+ {
113
+ "bootstrapAttributes": ["/^data-class/", "/Class$/"]
114
+ }
115
+ ```
116
+
117
+ Patterns must be wrapped in forward slashes. Optional flags (`i`, `g`, etc.) are supported: `/^data-class/i`.
118
+
119
+ ### File-Level Ignore
120
+
121
+ Add a comment at the top of a file to skip Bootstrap class sorting for the entire file:
122
+
123
+ ```html
124
+ <!-- prettier-bootstrap-ignore -->
125
+ <div class="mt-3 container">Will not be sorted</div>
126
+ ```
127
+
128
+ For JS/TS files:
129
+
130
+ ```js
131
+ // prettier-bootstrap-ignore
132
+ export default () => <div className="mt-3 container">Not sorted</div>
133
+ ```
134
+
135
+ Or block comment style:
136
+
137
+ ```js
138
+ /* prettier-bootstrap-ignore */
139
+ ```
140
+
141
+ ## Public Sorting API
142
+
143
+ For programmatic use (linters, codemods, build tools), import the sorter directly:
144
+
145
+ ```js
146
+ import { createSorter } from 'prettier-plugin-bootstrap/sorter'
147
+
148
+ const sorter = createSorter({ preserveDuplicates: false })
149
+
150
+ sorter.sort('mt-3 container p-2') // "container mt-3 p-2"
151
+ sorter.sortClasses(['mt-3', 'container']) // ["container", "mt-3"]
152
+ ```
153
+
81
154
  ## Supported Parsers
82
155
 
83
156
  - `html` — HTML files
@@ -108,6 +181,28 @@ When using with `prettier-plugin-astro`, list `prettier-plugin-bootstrap` **afte
108
181
  }
109
182
  ```
110
183
 
184
+ ## Plugin Compatibility
185
+
186
+ This plugin works alongside other Prettier plugins. Load order matters — `prettier-plugin-bootstrap` should come **last** so it can wrap the parsers registered by other plugins.
187
+
188
+ | Plugin | Compatible | Load Order |
189
+ | --------------------------------------- | ---------- | ---------------------------------------- |
190
+ | `prettier-plugin-svelte` | Yes | svelte first |
191
+ | `prettier-plugin-astro` | Yes | astro first |
192
+ | `prettier-plugin-tailwindcss` | N/A | Use one or the other (both sort classes) |
193
+ | `prettier-plugin-organize-imports` | Yes | Any order |
194
+ | `@trivago/prettier-plugin-sort-imports` | Yes | Any order |
195
+
196
+ ## FAQ
197
+
198
+ ### Does class sorting affect line wrapping?
199
+
200
+ Yes. Reordering classes changes the string length, which may cause Prettier to wrap lines differently based on your `printWidth` setting. This is expected — the formatting is still deterministic and consistent.
201
+
202
+ ### Can I use this with Tailwind CSS?
203
+
204
+ This plugin is designed specifically for Bootstrap's class system. If you use Tailwind CSS, use `prettier-plugin-tailwindcss` instead. They should not be used together as they have conflicting sort orders.
205
+
111
206
  ## Development
112
207
 
113
208
  ```bash
@@ -121,6 +216,7 @@ pnpm run typecheck
121
216
 
122
217
  - Prettier >= 3.0.0
123
218
  - Node.js >= 20
219
+ - Bootstrap 5 (class order)
124
220
 
125
221
  ## License
126
222
 
@@ -0,0 +1,23 @@
1
+ import { Options } from "prettier";
2
+
3
+ //#region src/types.d.ts
4
+ interface SortOptions {
5
+ preserveWhitespace?: boolean;
6
+ preserveDuplicates?: boolean;
7
+ }
8
+ interface BootstrapPluginOptions extends Options {
9
+ bootstrapAttributes?: string[];
10
+ bootstrapFunctions?: string[];
11
+ bootstrapPreserveWhitespace?: boolean;
12
+ bootstrapPreserveDuplicates?: boolean;
13
+ bootstrapVersion?: number;
14
+ }
15
+ type SortKey = [categoryIndex: number, breakpointIndex: number];
16
+ //#endregion
17
+ //#region src/class-order.d.ts
18
+ declare const BREAKPOINTS: readonly ["sm", "md", "lg", "xl", "xxl"];
19
+ declare const CLASS_ORDER: readonly string[];
20
+ declare function classKey(className: string): SortKey;
21
+ declare function sortClasses(classes: string[]): string[];
22
+ //#endregion
23
+ export { BootstrapPluginOptions as a, sortClasses as i, CLASS_ORDER as n, SortOptions as o, classKey as r, BREAKPOINTS as t };
@@ -0,0 +1,23 @@
1
+ import { Options } from "prettier";
2
+
3
+ //#region src/types.d.ts
4
+ interface SortOptions {
5
+ preserveWhitespace?: boolean;
6
+ preserveDuplicates?: boolean;
7
+ }
8
+ interface BootstrapPluginOptions extends Options {
9
+ bootstrapAttributes?: string[];
10
+ bootstrapFunctions?: string[];
11
+ bootstrapPreserveWhitespace?: boolean;
12
+ bootstrapPreserveDuplicates?: boolean;
13
+ bootstrapVersion?: number;
14
+ }
15
+ type SortKey = [categoryIndex: number, breakpointIndex: number];
16
+ //#endregion
17
+ //#region src/class-order.d.ts
18
+ declare const BREAKPOINTS: readonly ["sm", "md", "lg", "xl", "xxl"];
19
+ declare const CLASS_ORDER: readonly string[];
20
+ declare function classKey(className: string): SortKey;
21
+ declare function sortClasses(classes: string[]): string[];
22
+ //#endregion
23
+ export { BootstrapPluginOptions as a, sortClasses as i, CLASS_ORDER as n, SortOptions as o, classKey as r, BREAKPOINTS as t };
package/dist/index.cjs ADDED
@@ -0,0 +1,251 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sorting = require("./sorting-B-0731KP.cjs");
3
+ //#region src/traversal.ts
4
+ const AST_KEYS = [
5
+ "program",
6
+ "expression",
7
+ "left",
8
+ "right",
9
+ "argument",
10
+ "callee",
11
+ "object",
12
+ "property",
13
+ "consequent",
14
+ "alternate",
15
+ "init",
16
+ "test",
17
+ "update",
18
+ "declaration",
19
+ "declarations",
20
+ "openingElement",
21
+ "closingElement",
22
+ "attributes",
23
+ "value",
24
+ "elements",
25
+ "properties",
26
+ "arguments"
27
+ ];
28
+ function walk(node, visitor) {
29
+ if (!node) return;
30
+ visitor(node);
31
+ if (Array.isArray(node.children)) for (const child of node.children) walk(child, visitor);
32
+ if (node.body) {
33
+ if (Array.isArray(node.body)) for (const child of node.body) walk(child, visitor);
34
+ else if (typeof node.body === "object") walk(node.body, visitor);
35
+ }
36
+ for (const key of AST_KEYS) {
37
+ const child = node[key];
38
+ if (child) {
39
+ if (Array.isArray(child)) {
40
+ for (const item of child) if (item && typeof item === "object") walk(item, visitor);
41
+ } else if (typeof child === "object") walk(child, visitor);
42
+ }
43
+ }
44
+ }
45
+ function sortStringNode(node, sortOptions) {
46
+ if (!node) return;
47
+ if (node.type === "StringLiteral") {
48
+ const sorted = require_sorting.sortClassString(node.value, sortOptions);
49
+ node.value = sorted;
50
+ if (node.extra) {
51
+ node.extra.rawValue = sorted;
52
+ node.extra.raw = `"${sorted}"`;
53
+ }
54
+ return;
55
+ }
56
+ if (node.type === "Literal" && typeof node.value === "string") {
57
+ const sorted = require_sorting.sortClassString(node.value, sortOptions);
58
+ node.value = sorted;
59
+ if (node.raw) {
60
+ const quote = node.raw[0];
61
+ node.raw = `${quote}${sorted}${quote}`;
62
+ }
63
+ return;
64
+ }
65
+ if (node.type === "TemplateLiteral" && (!node.expressions || node.expressions.length === 0)) {
66
+ for (const quasi of node.quasis) if (quasi.value && typeof quasi.value.raw === "string") {
67
+ const sorted = require_sorting.sortClassString(quasi.value.raw, sortOptions);
68
+ quasi.value.raw = sorted;
69
+ quasi.value.cooked = sorted;
70
+ }
71
+ }
72
+ }
73
+ function processHtmlAst(ast, attrMatcher, _targetFunctions, sortOptions) {
74
+ const matchAttr = typeof attrMatcher === "function" ? attrMatcher : (name) => attrMatcher.includes(name);
75
+ walk(ast, (node) => {
76
+ if (node.attrs && Array.isArray(node.attrs)) {
77
+ for (const attr of node.attrs) if (matchAttr(attr.name) && typeof attr.value === "string") attr.value = require_sorting.sortClassString(attr.value, sortOptions);
78
+ }
79
+ if (node.attributes && Array.isArray(node.attributes)) {
80
+ for (const attr of node.attributes) if (matchAttr(attr.name || attr.key && attr.key.value) && attr.value) {
81
+ if (typeof attr.value === "string") {
82
+ if (attr.kind && attr.kind !== "quoted") continue;
83
+ if (attr.value.includes("${")) continue;
84
+ attr.value = require_sorting.sortClassString(attr.value, sortOptions);
85
+ } else if (attr.value && typeof attr.value.value === "string") {
86
+ if (attr.value.value.includes("${")) continue;
87
+ attr.value.value = require_sorting.sortClassString(attr.value.value, sortOptions);
88
+ }
89
+ }
90
+ }
91
+ });
92
+ return ast;
93
+ }
94
+ function processJsxAst(ast, attrMatcher, targetFunctions = [], sortOptions) {
95
+ const matchAttr = typeof attrMatcher === "function" ? attrMatcher : (name) => attrMatcher.includes(name);
96
+ const functionSet = new Set(targetFunctions);
97
+ walk(ast, (node) => {
98
+ if (node.type === "JSXAttribute" || node.type === "JSXSpreadAttribute") {
99
+ if (matchAttr(node.name && (node.name.name || node.name.value)) && node.value) {
100
+ if (node.value.type === "StringLiteral" || node.value.type === "Literal") {
101
+ const sorted = require_sorting.sortClassString(node.value.value, sortOptions);
102
+ node.value.value = sorted;
103
+ if (node.value.extra) {
104
+ node.value.extra.rawValue = sorted;
105
+ node.value.extra.raw = `"${sorted}"`;
106
+ }
107
+ if (node.value.raw) {
108
+ const quote = node.value.raw[0];
109
+ node.value.raw = `${quote}${sorted}${quote}`;
110
+ }
111
+ }
112
+ }
113
+ }
114
+ if (node.type === "CallExpression" && functionSet.size > 0) {
115
+ const callee = node.callee;
116
+ if (callee && callee.type === "Identifier" && functionSet.has(callee.name)) for (const arg of node.arguments || []) sortStringNode(arg, sortOptions);
117
+ }
118
+ });
119
+ return ast;
120
+ }
121
+ function walkSvelte(node, visitor) {
122
+ if (!node) return;
123
+ visitor(node);
124
+ if (node.fragment && Array.isArray(node.fragment.nodes)) for (const child of node.fragment.nodes) walkSvelte(child, visitor);
125
+ if (Array.isArray(node.children)) for (const child of node.children) walkSvelte(child, visitor);
126
+ }
127
+ function processSvelteAst(ast, attrMatcher, _targetFunctions, sortOptions) {
128
+ const matchAttr = typeof attrMatcher === "function" ? attrMatcher : (name) => attrMatcher.includes(name);
129
+ walkSvelte(ast, (node) => {
130
+ if (!node.attributes || !Array.isArray(node.attributes)) return;
131
+ for (const attr of node.attributes) {
132
+ if (attr.type !== "Attribute") continue;
133
+ if (!matchAttr(attr.name)) continue;
134
+ if (Array.isArray(attr.value)) {
135
+ for (const item of attr.value) if (item.type === "Text" && typeof item.data === "string") {
136
+ const sorted = require_sorting.sortClassString(item.data, sortOptions);
137
+ item.data = sorted;
138
+ if (typeof item.raw === "string") item.raw = sorted;
139
+ }
140
+ }
141
+ }
142
+ });
143
+ return ast;
144
+ }
145
+ //#endregion
146
+ //#region src/index.ts
147
+ const DEFAULT_ATTRIBUTES = ["class", "className"];
148
+ const IGNORE_RE = /(?:<!--\s*prettier-bootstrap-ignore\s*-->|\/\/\s*prettier-bootstrap-ignore|\/\*\s*prettier-bootstrap-ignore\s*\*\/)/;
149
+ const options = {
150
+ bootstrapAttributes: {
151
+ type: "string",
152
+ array: true,
153
+ default: [{ value: [] }],
154
+ category: "Bootstrap",
155
+ description: "Additional HTML attributes containing Bootstrap class lists to sort."
156
+ },
157
+ bootstrapFunctions: {
158
+ type: "string",
159
+ array: true,
160
+ default: [{ value: [] }],
161
+ category: "Bootstrap",
162
+ description: "Function names whose arguments are Bootstrap class lists (e.g. clsx, classNames)."
163
+ },
164
+ bootstrapPreserveWhitespace: {
165
+ type: "boolean",
166
+ default: false,
167
+ category: "Bootstrap",
168
+ description: "Preserve original whitespace between classes instead of normalizing to single spaces."
169
+ },
170
+ bootstrapPreserveDuplicates: {
171
+ type: "boolean",
172
+ default: true,
173
+ category: "Bootstrap",
174
+ description: "Keep duplicate class names. Set to false to remove duplicates."
175
+ },
176
+ bootstrapVersion: {
177
+ type: "int",
178
+ default: 5,
179
+ category: "Bootstrap",
180
+ description: "Bootstrap version (for future version-specific sorting rules)."
181
+ }
182
+ };
183
+ function buildAttrMatcher(allAttrs) {
184
+ const plainAttrs = [];
185
+ const regexAttrs = [];
186
+ for (const attr of allAttrs) {
187
+ const m = attr.match(/^\/(.+)\/([gimsuy]*)$/);
188
+ if (m) regexAttrs.push(new RegExp(m[1], m[2]));
189
+ else plainAttrs.push(attr);
190
+ }
191
+ return (name) => plainAttrs.includes(name) || regexAttrs.some((re) => re.test(name));
192
+ }
193
+ function createParserWrapper(parserName, processAst, astFormat) {
194
+ const wrapper = {
195
+ astFormat,
196
+ locStart(node) {
197
+ return node.range?.[0] ?? node.start ?? node.sourceSpan?.start?.offset ?? 0;
198
+ },
199
+ locEnd(node) {
200
+ return node.range?.[1] ?? node.end ?? node.sourceSpan?.end?.offset ?? 0;
201
+ },
202
+ async parse(text, options) {
203
+ const plugins = options.plugins || [];
204
+ let originalParser = null;
205
+ for (const plugin of plugins) {
206
+ if (typeof plugin !== "object" || !plugin.parsers) continue;
207
+ const candidate = plugin.parsers[parserName];
208
+ if (!candidate) continue;
209
+ let resolved = candidate;
210
+ if (typeof candidate === "function" && !candidate.parse) resolved = await candidate();
211
+ if (resolved && typeof resolved.parse === "function" && resolved.parse !== wrapper.parse) {
212
+ originalParser = resolved;
213
+ break;
214
+ }
215
+ }
216
+ if (!originalParser) throw new Error(`prettier-plugin-bootstrap: could not find the "${parserName}" parser. Make sure Prettier and the relevant parser plugin are installed.`);
217
+ if (originalParser.locStart) wrapper.locStart = originalParser.locStart;
218
+ if (originalParser.locEnd) wrapper.locEnd = originalParser.locEnd;
219
+ if (originalParser.astFormat) wrapper.astFormat = originalParser.astFormat;
220
+ const ast = await originalParser.parse(text, options);
221
+ if (IGNORE_RE.test(text.slice(0, 1500))) return ast;
222
+ const targetAttrs = [...DEFAULT_ATTRIBUTES, ...options.bootstrapAttributes || []];
223
+ const targetFunctions = options.bootstrapFunctions || [];
224
+ return processAst(ast, buildAttrMatcher(targetAttrs), targetFunctions, {
225
+ preserveWhitespace: options.bootstrapPreserveWhitespace ?? false,
226
+ preserveDuplicates: options.bootstrapPreserveDuplicates ?? true
227
+ });
228
+ }
229
+ };
230
+ return wrapper;
231
+ }
232
+ const parsers = {
233
+ html: createParserWrapper("html", processHtmlAst, "html"),
234
+ vue: createParserWrapper("vue", processHtmlAst, "html"),
235
+ angular: createParserWrapper("angular", processHtmlAst, "html"),
236
+ babel: createParserWrapper("babel", processJsxAst, "estree"),
237
+ "babel-ts": createParserWrapper("babel-ts", processJsxAst, "estree"),
238
+ typescript: createParserWrapper("typescript", processJsxAst, "estree"),
239
+ acorn: createParserWrapper("acorn", processJsxAst, "estree"),
240
+ meriyah: createParserWrapper("meriyah", processJsxAst, "estree"),
241
+ astro: createParserWrapper("astro", processHtmlAst, "astro"),
242
+ svelte: createParserWrapper("svelte", processSvelteAst, "svelte-ast")
243
+ };
244
+ //#endregion
245
+ exports.BREAKPOINTS = require_sorting.BREAKPOINTS;
246
+ exports.CLASS_ORDER = require_sorting.CLASS_ORDER;
247
+ exports.buildAttrMatcher = buildAttrMatcher;
248
+ exports.classKey = require_sorting.classKey;
249
+ exports.options = options;
250
+ exports.parsers = parsers;
251
+ exports.sortClasses = require_sorting.sortClasses;
@@ -0,0 +1,46 @@
1
+ import { a as BootstrapPluginOptions, i as sortClasses, n as CLASS_ORDER, o as SortOptions, r as classKey, t as BREAKPOINTS } from "./class-order-UKlp_Ej7.cjs";
2
+ import { Parser } from "prettier";
3
+
4
+ //#region src/index.d.ts
5
+ declare const options: {
6
+ bootstrapAttributes: {
7
+ type: "string";
8
+ array: true;
9
+ default: {
10
+ value: never[];
11
+ }[];
12
+ category: string;
13
+ description: string;
14
+ };
15
+ bootstrapFunctions: {
16
+ type: "string";
17
+ array: true;
18
+ default: {
19
+ value: never[];
20
+ }[];
21
+ category: string;
22
+ description: string;
23
+ };
24
+ bootstrapPreserveWhitespace: {
25
+ type: "boolean";
26
+ default: boolean;
27
+ category: string;
28
+ description: string;
29
+ };
30
+ bootstrapPreserveDuplicates: {
31
+ type: "boolean";
32
+ default: boolean;
33
+ category: string;
34
+ description: string;
35
+ };
36
+ bootstrapVersion: {
37
+ type: "int";
38
+ default: number;
39
+ category: string;
40
+ description: string;
41
+ };
42
+ };
43
+ declare function buildAttrMatcher(allAttrs: string[]): (name: string) => boolean;
44
+ declare const parsers: Record<string, Parser>;
45
+ //#endregion
46
+ export { BREAKPOINTS, type BootstrapPluginOptions, CLASS_ORDER, type SortOptions, buildAttrMatcher, classKey, options, parsers, sortClasses };
package/dist/index.d.mts CHANGED
@@ -1,23 +1,11 @@
1
- import { Options, Parser } from "prettier";
1
+ import { a as BootstrapPluginOptions, i as sortClasses, n as CLASS_ORDER, o as SortOptions, r as classKey, t as BREAKPOINTS } from "./class-order-BYtmS-1R.mjs";
2
+ import { Parser } from "prettier";
2
3
 
3
- //#region src/types.d.ts
4
- interface BootstrapPluginOptions extends Options {
5
- bootstrapAttributes?: string[];
6
- bootstrapFunctions?: string[];
7
- }
8
- type SortKey = [categoryIndex: number, breakpointIndex: number];
9
- //#endregion
10
- //#region src/class-order.d.ts
11
- declare const BREAKPOINTS: readonly ["sm", "md", "lg", "xl", "xxl"];
12
- declare const CLASS_ORDER: readonly string[];
13
- declare function classKey(className: string): SortKey;
14
- declare function sortClasses(classes: string[]): string[];
15
- //#endregion
16
4
  //#region src/index.d.ts
17
5
  declare const options: {
18
6
  bootstrapAttributes: {
19
7
  type: "string";
20
- array: boolean;
8
+ array: true;
21
9
  default: {
22
10
  value: never[];
23
11
  }[];
@@ -26,14 +14,33 @@ declare const options: {
26
14
  };
27
15
  bootstrapFunctions: {
28
16
  type: "string";
29
- array: boolean;
17
+ array: true;
30
18
  default: {
31
19
  value: never[];
32
20
  }[];
33
21
  category: string;
34
22
  description: string;
35
23
  };
24
+ bootstrapPreserveWhitespace: {
25
+ type: "boolean";
26
+ default: boolean;
27
+ category: string;
28
+ description: string;
29
+ };
30
+ bootstrapPreserveDuplicates: {
31
+ type: "boolean";
32
+ default: boolean;
33
+ category: string;
34
+ description: string;
35
+ };
36
+ bootstrapVersion: {
37
+ type: "int";
38
+ default: number;
39
+ category: string;
40
+ description: string;
41
+ };
36
42
  };
37
- declare const parsers: Record<string, Partial<Parser>>;
43
+ declare function buildAttrMatcher(allAttrs: string[]): (name: string) => boolean;
44
+ declare const parsers: Record<string, Parser>;
38
45
  //#endregion
39
- export { BREAKPOINTS, type BootstrapPluginOptions, CLASS_ORDER, classKey, options, parsers, sortClasses };
46
+ export { BREAKPOINTS, type BootstrapPluginOptions, CLASS_ORDER, type SortOptions, buildAttrMatcher, classKey, options, parsers, sortClasses };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Parser } from 'prettier';
2
2
  export declare const options: {
3
3
  bootstrapAttributes: {
4
4
  type: "string";
5
- array: boolean;
5
+ array: true;
6
6
  default: {
7
7
  value: never[];
8
8
  }[];
@@ -11,14 +11,34 @@ export declare const options: {
11
11
  };
12
12
  bootstrapFunctions: {
13
13
  type: "string";
14
- array: boolean;
14
+ array: true;
15
15
  default: {
16
16
  value: never[];
17
17
  }[];
18
18
  category: string;
19
19
  description: string;
20
20
  };
21
+ bootstrapPreserveWhitespace: {
22
+ type: "boolean";
23
+ default: boolean;
24
+ category: string;
25
+ description: string;
26
+ };
27
+ bootstrapPreserveDuplicates: {
28
+ type: "boolean";
29
+ default: boolean;
30
+ category: string;
31
+ description: string;
32
+ };
33
+ bootstrapVersion: {
34
+ type: "int";
35
+ default: number;
36
+ category: string;
37
+ description: string;
38
+ };
21
39
  };
22
- export declare const parsers: Record<string, Partial<Parser>>;
23
- export type { BootstrapPluginOptions } from './types';
40
+ declare function buildAttrMatcher(allAttrs: string[]): (name: string) => boolean;
41
+ export declare const parsers: Record<string, Parser>;
42
+ export { buildAttrMatcher };
43
+ export type { BootstrapPluginOptions, SortOptions } from './types';
24
44
  export { sortClasses, classKey, CLASS_ORDER, BREAKPOINTS } from './class-order';