Skip to content

Commit 0847bc2

Browse files
committed
chore: revamp how we export types
1 parent 49954bc commit 0847bc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1325
-1132
lines changed

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
# Enforce Unix newlines
22
* text=auto eol=lf
3+
4+
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
5+
/.yarn/releases/** binary
6+
/.yarn/plugins/** binary

.github/workflows/main.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,18 @@ jobs:
2424
cache: yarn
2525
- run: yarn install
2626
- run: yarn lint
27-
- run: yarn typecheck
27+
- run: yarn test:types
28+
types:
29+
name: Types
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: actions/setup-node@v4
34+
with:
35+
node-version: ${{ env.NODE }}
36+
cache: yarn
37+
- run: yarn install
38+
- run: yarn test:types
2839
test:
2940
name: ${{ matrix.os }} Node.js ${{ matrix.node-version }}
3041
strategy:

.gitignore

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1-
.pnp.*
1+
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
22
.yarn/*
33
!.yarn/patches
44
!.yarn/plugins
55
!.yarn/releases
66
!.yarn/sdks
77
!.yarn/versions
88

9-
node_modules
9+
# https://github.com/github/gitignore/blob/main/Global/Vim.gitignore
10+
[._]*.s[a-v][a-z]
11+
!*.svg
12+
[._]*.sw[a-p]
13+
[._]s[a-rt-v][a-z]
14+
[._]ss[a-gi-z]
15+
[._]sw[a-p]
16+
Session.vim
17+
Sessionx.vim
18+
.netrwhist
19+
*~
20+
tags
21+
[._]*.un~
22+
23+
# Ignore generated files for browser, CommonJS, or types
1024
dist
25+
types
26+
27+
node_modules
1128
test/regression-fixtures
1229
test/regression-diffs
1330
test/cli/output
@@ -16,11 +33,3 @@ coverage
1633
.vscode
1734
*.log
1835
package-lock.json
19-
20-
# https://github.com/github/gitignore/blob/main/Global/Vim.gitignore
21-
[._]*.s[a-v][a-z]
22-
!*.svg # comment out if you don't need vector files
23-
[._]*.sw[a-p]
24-
[._]s[a-rt-v][a-z]
25-
[._]ss[a-gi-z]
26-
[._]sw[a-p]

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ See: [SECURITY.md](./SECURITY.md)
2121
### Requirements
2222

2323
- [Git](https://git-scm.com/)
24-
- [Node.js 20](https://nodejs.org/) or later
24+
- [Node.js >=16](https://nodejs.org/) — Our CI pipeline includes Node.js v16, so even development code must be runnable in a Node.js v16 environment.
2525

2626
### Getting Started
2727

@@ -55,7 +55,7 @@ You should read our [Plugin Architecture](https://svgo.dev/docs/plugins-api/) do
5555

5656
SVGO plugins can optionally have parameters. These can be consumed by the plugin to tailor the behavior.
5757

58-
Parameters must have types declared in a [`@typedef`](https://jsdoc.app/tags-typedef) at the top of the file. For new plugins, you must also append the appropriate type in [`plugins/plugin-types.d.ts`](https://github.com/svg/svgo/blob/main/plugins/plugins-types.d.ts). This way built-in plugins will have code completion and type checking as you'd expect while editing the plugin.
58+
Parameters must have types declared in a [`@typedef`](https://jsdoc.app/tags-typedef) at the top of the file. For new plugins, you must also append the appropriate type in [`lib/types.d.ts`](https://github.com/svg/svgo/blob/main/lib/types.d.ts). This way built-in plugins will have code completion and type checking as you'd expect while editing the plugin.
5959

6060
## Documentation
6161

cspell.jsonc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@
4747
"Dmitry",
4848
"Keerthi",
4949
],
50-
"ignorePaths": ["*.svg.txt", "*.svg", "cspell.jsonc", "LICENSE"],
50+
"ignorePaths": [
51+
".gitignore",
52+
"*.svg.txt",
53+
"*.svg",
54+
"cspell.jsonc",
55+
"LICENSE",
56+
],
5157
"ignoreRegExpList": [
5258
"-moz", // Mozilla Firefox CSS prefix
5359
"'.+?.svg',", // path to file with .svg extension

eslint.config.mjs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import js from '@eslint/js';
22
import globals from 'globals';
33

4-
/**
5-
* @typedef {import('eslint').Linter.Config} Config
6-
*/
7-
8-
/** @type {Config[]} */
4+
/** @type {import('eslint').Linter.Config[]} */
95
export default [
106
{
117
ignores: [

lib/builtin.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@ import * as reusePaths from '../plugins/reusePaths.js';
5353
import * as sortAttrs from '../plugins/sortAttrs.js';
5454
import * as sortDefsChildren from '../plugins/sortDefsChildren.js';
5555

56-
export const builtin = Object.freeze([
56+
/**
57+
* Plugins that are bundled with SVGO. This includes plugin presets, and plugins
58+
* that are not enabled by default.
59+
*
60+
* @type {ReadonlyArray<{[Name in keyof import('./types.js').PluginsParams]: import('./types.js').BuiltinPluginOrPreset<Name, import('./types.js').PluginsParams[Name]>;}[keyof import('./types.js').PluginsParams]>}
61+
*/
62+
export const builtinPlugins = Object.freeze([
5763
presetDefault,
5864
addAttributesToSVGElement,
5965
addClassesToSVGElement,

lib/parser.js

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
1-
/**
2-
* @typedef {import('./types.js').XastNode} XastNode
3-
* @typedef {import('./types.js').XastInstruction} XastInstruction
4-
* @typedef {import('./types.js').XastDoctype} XastDoctype
5-
* @typedef {import('./types.js').XastComment} XastComment
6-
* @typedef {import('./types.js').XastRoot} XastRoot
7-
* @typedef {import('./types.js').XastElement} XastElement
8-
* @typedef {import('./types.js').XastCdata} XastCdata
9-
* @typedef {import('./types.js').XastText} XastText
10-
* @typedef {import('./types.js').XastParent} XastParent
11-
* @typedef {import('./types.js').XastChild} XastChild
12-
*/
13-
141
import SAX from 'sax';
152
import { textElems } from '../plugins/_collections.js';
163

@@ -20,9 +7,9 @@ export class SvgoParserError extends Error {
207
* @param {number} line
218
* @param {number} column
229
* @param {string} source
23-
* @param {string | undefined} file
10+
* @param {string=} file
2411
*/
25-
constructor(message, line, column, source, file = undefined) {
12+
constructor(message, line, column, source, file) {
2613
super(message);
2714
this.name = 'SvgoParserError';
2815
this.message = `${file || '<input>'}:${line}:${column}: ${message}`;
@@ -88,26 +75,26 @@ const config = {
8875
*
8976
* @param {string} data
9077
* @param {string=} from
91-
* @returns {XastRoot}
78+
* @returns {import('./types.js').XastRoot}
9279
*/
9380
export const parseSvg = (data, from) => {
9481
const sax = SAX.parser(config.strict, config);
95-
/** @type {XastRoot} */
82+
/** @type {import('./types.js').XastRoot} */
9683
const root = { type: 'root', children: [] };
97-
/** @type {XastParent} */
84+
/** @type {import('./types.js').XastParent} */
9885
let current = root;
99-
/** @type {XastParent[]} */
86+
/** @type {import('./types.js').XastParent[]} */
10087
const stack = [root];
10188

10289
/**
103-
* @param {XastChild} node
90+
* @param {import('./types.js').XastChild} node
10491
*/
10592
const pushToContent = (node) => {
10693
current.children.push(node);
10794
};
10895

10996
sax.ondoctype = (doctype) => {
110-
/** @type {XastDoctype} */
97+
/** @type {import('./types.js').XastDoctype} */
11198
const node = {
11299
type: 'doctype',
113100
// TODO parse doctype for name, public and system to match xast
@@ -129,7 +116,7 @@ export const parseSvg = (data, from) => {
129116
};
130117

131118
sax.onprocessinginstruction = (data) => {
132-
/** @type {XastInstruction} */
119+
/** @type {import('./types.js').XastInstruction} */
133120
const node = {
134121
type: 'instruction',
135122
name: data.name,
@@ -139,7 +126,7 @@ export const parseSvg = (data, from) => {
139126
};
140127

141128
sax.oncomment = (comment) => {
142-
/** @type {XastComment} */
129+
/** @type {import('./types.js').XastComment} */
143130
const node = {
144131
type: 'comment',
145132
value: comment.trim(),
@@ -148,7 +135,7 @@ export const parseSvg = (data, from) => {
148135
};
149136

150137
sax.oncdata = (cdata) => {
151-
/** @type {XastCdata} */
138+
/** @type {import('./types.js').XastCdata} */
152139
const node = {
153140
type: 'cdata',
154141
value: cdata,
@@ -157,7 +144,7 @@ export const parseSvg = (data, from) => {
157144
};
158145

159146
sax.onopentag = (data) => {
160-
/** @type {XastElement} */
147+
/** @type {import('./types.js').XastElement} */
161148
const element = {
162149
type: 'element',
163150
name: data.name,
@@ -176,14 +163,14 @@ export const parseSvg = (data, from) => {
176163
if (current.type === 'element') {
177164
// prevent trimming of meaningful whitespace inside textual tags
178165
if (textElems.has(current.name)) {
179-
/** @type {XastText} */
166+
/** @type {import('./types.js').XastText} */
180167
const node = {
181168
type: 'text',
182169
value: text,
183170
};
184171
pushToContent(node);
185172
} else if (/\S/.test(text)) {
186-
/** @type {XastText} */
173+
/** @type {import('./types.js').XastText} */
187174
const node = {
188175
type: 'text',
189176
value: text.trim(),

lib/path.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
import { removeLeadingZero, toFixed } from './svgo/tools.js';
66

77
/**
8-
* @typedef {import('./types.js').PathDataItem} PathDataItem
9-
* @typedef {import('./types.js').PathDataCommand} PathDataCommand
108
* @typedef {'none' | 'sign' | 'whole' | 'decimal_point' | 'decimal' | 'e' | 'exponent_sign' | 'exponent'} ReadNumberState
119
*
1210
* @typedef StringifyPathDataOptions
13-
* @property {ReadonlyArray<PathDataItem>} pathData
11+
* @property {ReadonlyArray<import('./types.js').PathDataItem>} pathData
1412
* @property {number=} precision
1513
* @property {boolean=} disableSpaceAfterFlags
1614
*/
@@ -40,7 +38,7 @@ const argsCountPerCommand = {
4038

4139
/**
4240
* @param {string} c
43-
* @returns {c is PathDataCommand}
41+
* @returns {c is import('./types.js').PathDataCommand}
4442
*/
4543
const isCommand = (c) => {
4644
return c in argsCountPerCommand;
@@ -138,12 +136,12 @@ const readNumber = (string, cursor) => {
138136

139137
/**
140138
* @param {string} string
141-
* @returns {PathDataItem[]}
139+
* @returns {import('./types.js').PathDataItem[]}
142140
*/
143141
export const parsePathData = (string) => {
144-
/** @type {PathDataItem[]} */
142+
/** @type {import('./types.js').PathDataItem[]} */
145143
const pathData = [];
146-
/** @type {?PathDataCommand} */
144+
/** @type {?import('./types.js').PathDataCommand} */
147145
let command = null;
148146
let args = /** @type {number[]} */ ([]);
149147
let argsCount = 0;

lib/path.test.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { parsePathData, stringifyPathData } from './path.js';
22

3-
/**
4-
* @typedef {import('../lib/types.js').PathDataItem} PathDataItem
5-
*/
6-
73
describe('parse path data', () => {
84
it('should allow spaces between commands', () => {
95
expect(parsePathData('M0 10 L \n\r\t20 30')).toStrictEqual([
@@ -154,7 +150,7 @@ describe('stringify path data', () => {
154150
).toBe('M.1 1e-7 2 2');
155151
});
156152
it('should configure precision', () => {
157-
/** @type {ReadonlyArray<PathDataItem>} */
153+
/** @type {ReadonlyArray<import('../lib/types.js').PathDataItem>} */
158154
const pathData = [
159155
{ command: 'M', args: [0, -1.9876] },
160156
{ command: 'L', args: [0.3, 3.14159265] },
@@ -175,7 +171,7 @@ describe('stringify path data', () => {
175171
).toBe('M0-2 0 3 0-3 100 200');
176172
});
177173
it('allows to avoid spaces after arc flags', () => {
178-
/** @type {ReadonlyArray<PathDataItem>} */
174+
/** @type {ReadonlyArray<import('../lib/types.js').PathDataItem>} */
179175
const pathData = [
180176
{ command: 'M', args: [0, 0] },
181177
{ command: 'A', args: [50, 50, 10, 1, 0, 0.2, 20] },

0 commit comments

Comments
 (0)