font-range 0.2.0 → 1.0.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.
Files changed (44) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.json +12 -1
  3. package/.gitattributes +3 -0
  4. package/.vim/coc-settings.json +6 -0
  5. package/.yarn/plugins/@yarnpkg/plugin-outdated.cjs +35 -0
  6. package/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
  7. package/.yarn/sdks/eslint/bin/eslint.js +20 -0
  8. package/.yarn/sdks/eslint/lib/api.js +20 -0
  9. package/.yarn/sdks/eslint/package.json +6 -0
  10. package/.yarn/sdks/integrations.yml +6 -0
  11. package/.yarn/sdks/prettier/index.js +20 -0
  12. package/.yarn/sdks/prettier/package.json +6 -0
  13. package/.yarn/sdks/typescript/bin/tsc +20 -0
  14. package/.yarn/sdks/typescript/bin/tsserver +20 -0
  15. package/.yarn/sdks/typescript/lib/tsc.js +20 -0
  16. package/.yarn/sdks/typescript/lib/tsserver.js +223 -0
  17. package/.yarn/sdks/typescript/lib/tsserverlibrary.js +223 -0
  18. package/.yarn/sdks/typescript/lib/typescript.js +20 -0
  19. package/.yarn/sdks/typescript/package.json +6 -0
  20. package/README.md +141 -43
  21. package/__tests__/css_load.test.ts +52 -0
  22. package/__tests__/font/NotoSansKR-Local.css +3 -2
  23. package/__tests__/font/subset_glyphs.txt +1 -0
  24. package/__tests__/main.test.ts +241 -52
  25. package/__tests__/preset.test.ts +64 -0
  26. package/__tests__/shared.ts +25 -0
  27. package/build/main.d.ts +49 -0
  28. package/build/main.js +363 -0
  29. package/build/worker.d.ts +5 -0
  30. package/build/worker.js +10 -0
  31. package/jest.config.js +5 -5
  32. package/package.json +29 -25
  33. package/requirements.txt +7 -4
  34. package/src/main.ts +356 -106
  35. package/src/{types.ts → types.d.ts} +0 -2
  36. package/src/worker.ts +12 -0
  37. package/tsconfig.json +4 -0
  38. package/tsconfig.release.json +4 -2
  39. package/.github/workflows/nodejs.yml +0 -36
  40. package/.github/workflows/npm-publish.yml +0 -106
  41. package/build/src/main.js +0 -199
  42. package/build/src/main.js.map +0 -1
  43. package/build/src/types.js +0 -3
  44. package/build/src/types.js.map +0 -1
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {existsSync} = require(`fs`);
4
+ const {createRequire} = require(`module`);
5
+ const {resolve} = require(`path`);
6
+
7
+ const relPnpApiPath = "../../../../.pnp.cjs";
8
+
9
+ const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10
+ const absRequire = createRequire(absPnpApiPath);
11
+
12
+ const moduleWrapper = tsserver => {
13
+ if (!process.versions.pnp) {
14
+ return tsserver;
15
+ }
16
+
17
+ const {isAbsolute} = require(`path`);
18
+ const pnpApi = require(`pnpapi`);
19
+
20
+ const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
21
+ const isPortal = str => str.startsWith("portal:/");
22
+ const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
23
+
24
+ const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
25
+ return `${locator.name}@${locator.reference}`;
26
+ }));
27
+
28
+ // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
29
+ // doesn't understand. This layer makes sure to remove the protocol
30
+ // before forwarding it to TS, and to add it back on all returned paths.
31
+
32
+ function toEditorPath(str) {
33
+ // We add the `zip:` prefix to both `.zip/` paths and virtual paths
34
+ if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
35
+ // We also take the opportunity to turn virtual paths into physical ones;
36
+ // this makes it much easier to work with workspaces that list peer
37
+ // dependencies, since otherwise Ctrl+Click would bring us to the virtual
38
+ // file instances instead of the real ones.
39
+ //
40
+ // We only do this to modules owned by the the dependency tree roots.
41
+ // This avoids breaking the resolution when jumping inside a vendor
42
+ // with peer dep (otherwise jumping into react-dom would show resolution
43
+ // errors on react).
44
+ //
45
+ const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
46
+ if (resolved) {
47
+ const locator = pnpApi.findPackageLocator(resolved);
48
+ if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
49
+ str = resolved;
50
+ }
51
+ }
52
+
53
+ str = normalize(str);
54
+
55
+ if (str.match(/\.zip\//)) {
56
+ switch (hostInfo) {
57
+ // Absolute VSCode `Uri.fsPath`s need to start with a slash.
58
+ // VSCode only adds it automatically for supported schemes,
59
+ // so we have to do it manually for the `zip` scheme.
60
+ // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
61
+ //
62
+ // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
63
+ //
64
+ // 2021-10-08: VSCode changed the format in 1.61.
65
+ // Before | ^zip:/c:/foo/bar.zip/package.json
66
+ // After | ^/zip//c:/foo/bar.zip/package.json
67
+ //
68
+ // 2022-04-06: VSCode changed the format in 1.66.
69
+ // Before | ^/zip//c:/foo/bar.zip/package.json
70
+ // After | ^/zip/c:/foo/bar.zip/package.json
71
+ //
72
+ // 2022-05-06: VSCode changed the format in 1.68
73
+ // Before | ^/zip/c:/foo/bar.zip/package.json
74
+ // After | ^/zip//c:/foo/bar.zip/package.json
75
+ //
76
+ case `vscode <1.61`: {
77
+ str = `^zip:${str}`;
78
+ } break;
79
+
80
+ case `vscode <1.66`: {
81
+ str = `^/zip/${str}`;
82
+ } break;
83
+
84
+ case `vscode <1.68`: {
85
+ str = `^/zip${str}`;
86
+ } break;
87
+
88
+ case `vscode`: {
89
+ str = `^/zip/${str}`;
90
+ } break;
91
+
92
+ // To make "go to definition" work,
93
+ // We have to resolve the actual file system path from virtual path
94
+ // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
95
+ case `coc-nvim`: {
96
+ str = normalize(resolved).replace(/\.zip\//, `.zip::`);
97
+ str = resolve(`zipfile:${str}`);
98
+ } break;
99
+
100
+ // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
101
+ // We have to resolve the actual file system path from virtual path,
102
+ // everything else is up to neovim
103
+ case `neovim`: {
104
+ str = normalize(resolved).replace(/\.zip\//, `.zip::`);
105
+ str = `zipfile://${str}`;
106
+ } break;
107
+
108
+ default: {
109
+ str = `zip:${str}`;
110
+ } break;
111
+ }
112
+ }
113
+ }
114
+
115
+ return str;
116
+ }
117
+
118
+ function fromEditorPath(str) {
119
+ switch (hostInfo) {
120
+ case `coc-nvim`: {
121
+ str = str.replace(/\.zip::/, `.zip/`);
122
+ // The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
123
+ // So in order to convert it back, we use .* to match all the thing
124
+ // before `zipfile:`
125
+ return process.platform === `win32`
126
+ ? str.replace(/^.*zipfile:\//, ``)
127
+ : str.replace(/^.*zipfile:/, ``);
128
+ } break;
129
+
130
+ case `neovim`: {
131
+ str = str.replace(/\.zip::/, `.zip/`);
132
+ // The path for neovim is in format of zipfile:///<pwd>/.yarn/...
133
+ return str.replace(/^zipfile:\/\//, ``);
134
+ } break;
135
+
136
+ case `vscode`:
137
+ default: {
138
+ return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
139
+ } break;
140
+ }
141
+ }
142
+
143
+ // Force enable 'allowLocalPluginLoads'
144
+ // TypeScript tries to resolve plugins using a path relative to itself
145
+ // which doesn't work when using the global cache
146
+ // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
147
+ // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
148
+ // TypeScript already does local loads and if this code is running the user trusts the workspace
149
+ // https://github.com/microsoft/vscode/issues/45856
150
+ const ConfiguredProject = tsserver.server.ConfiguredProject;
151
+ const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
152
+ ConfiguredProject.prototype.enablePluginsWithOptions = function() {
153
+ this.projectService.allowLocalPluginLoads = true;
154
+ return originalEnablePluginsWithOptions.apply(this, arguments);
155
+ };
156
+
157
+ // And here is the point where we hijack the VSCode <-> TS communications
158
+ // by adding ourselves in the middle. We locate everything that looks
159
+ // like an absolute path of ours and normalize it.
160
+
161
+ const Session = tsserver.server.Session;
162
+ const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
163
+ let hostInfo = `unknown`;
164
+
165
+ Object.assign(Session.prototype, {
166
+ onMessage(/** @type {string | object} */ message) {
167
+ const isStringMessage = typeof message === 'string';
168
+ const parsedMessage = isStringMessage ? JSON.parse(message) : message;
169
+
170
+ if (
171
+ parsedMessage != null &&
172
+ typeof parsedMessage === `object` &&
173
+ parsedMessage.arguments &&
174
+ typeof parsedMessage.arguments.hostInfo === `string`
175
+ ) {
176
+ hostInfo = parsedMessage.arguments.hostInfo;
177
+ if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
178
+ const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
179
+ // The RegExp from https://semver.org/ but without the caret at the start
180
+ /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
181
+ ) ?? []).map(Number)
182
+
183
+ if (major === 1) {
184
+ if (minor < 61) {
185
+ hostInfo += ` <1.61`;
186
+ } else if (minor < 66) {
187
+ hostInfo += ` <1.66`;
188
+ } else if (minor < 68) {
189
+ hostInfo += ` <1.68`;
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
196
+ return typeof value === 'string' ? fromEditorPath(value) : value;
197
+ });
198
+
199
+ return originalOnMessage.call(
200
+ this,
201
+ isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
202
+ );
203
+ },
204
+
205
+ send(/** @type {any} */ msg) {
206
+ return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
207
+ return typeof value === `string` ? toEditorPath(value) : value;
208
+ })));
209
+ }
210
+ });
211
+
212
+ return tsserver;
213
+ };
214
+
215
+ if (existsSync(absPnpApiPath)) {
216
+ if (!process.versions.pnp) {
217
+ // Setup the environment to be able to require typescript/lib/tsserver.js
218
+ require(absPnpApiPath).setup();
219
+ }
220
+ }
221
+
222
+ // Defer to the real typescript/lib/tsserver.js your application uses
223
+ module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {existsSync} = require(`fs`);
4
+ const {createRequire} = require(`module`);
5
+ const {resolve} = require(`path`);
6
+
7
+ const relPnpApiPath = "../../../../.pnp.cjs";
8
+
9
+ const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10
+ const absRequire = createRequire(absPnpApiPath);
11
+
12
+ const moduleWrapper = tsserver => {
13
+ if (!process.versions.pnp) {
14
+ return tsserver;
15
+ }
16
+
17
+ const {isAbsolute} = require(`path`);
18
+ const pnpApi = require(`pnpapi`);
19
+
20
+ const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
21
+ const isPortal = str => str.startsWith("portal:/");
22
+ const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
23
+
24
+ const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
25
+ return `${locator.name}@${locator.reference}`;
26
+ }));
27
+
28
+ // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
29
+ // doesn't understand. This layer makes sure to remove the protocol
30
+ // before forwarding it to TS, and to add it back on all returned paths.
31
+
32
+ function toEditorPath(str) {
33
+ // We add the `zip:` prefix to both `.zip/` paths and virtual paths
34
+ if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
35
+ // We also take the opportunity to turn virtual paths into physical ones;
36
+ // this makes it much easier to work with workspaces that list peer
37
+ // dependencies, since otherwise Ctrl+Click would bring us to the virtual
38
+ // file instances instead of the real ones.
39
+ //
40
+ // We only do this to modules owned by the the dependency tree roots.
41
+ // This avoids breaking the resolution when jumping inside a vendor
42
+ // with peer dep (otherwise jumping into react-dom would show resolution
43
+ // errors on react).
44
+ //
45
+ const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
46
+ if (resolved) {
47
+ const locator = pnpApi.findPackageLocator(resolved);
48
+ if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
49
+ str = resolved;
50
+ }
51
+ }
52
+
53
+ str = normalize(str);
54
+
55
+ if (str.match(/\.zip\//)) {
56
+ switch (hostInfo) {
57
+ // Absolute VSCode `Uri.fsPath`s need to start with a slash.
58
+ // VSCode only adds it automatically for supported schemes,
59
+ // so we have to do it manually for the `zip` scheme.
60
+ // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
61
+ //
62
+ // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
63
+ //
64
+ // 2021-10-08: VSCode changed the format in 1.61.
65
+ // Before | ^zip:/c:/foo/bar.zip/package.json
66
+ // After | ^/zip//c:/foo/bar.zip/package.json
67
+ //
68
+ // 2022-04-06: VSCode changed the format in 1.66.
69
+ // Before | ^/zip//c:/foo/bar.zip/package.json
70
+ // After | ^/zip/c:/foo/bar.zip/package.json
71
+ //
72
+ // 2022-05-06: VSCode changed the format in 1.68
73
+ // Before | ^/zip/c:/foo/bar.zip/package.json
74
+ // After | ^/zip//c:/foo/bar.zip/package.json
75
+ //
76
+ case `vscode <1.61`: {
77
+ str = `^zip:${str}`;
78
+ } break;
79
+
80
+ case `vscode <1.66`: {
81
+ str = `^/zip/${str}`;
82
+ } break;
83
+
84
+ case `vscode <1.68`: {
85
+ str = `^/zip${str}`;
86
+ } break;
87
+
88
+ case `vscode`: {
89
+ str = `^/zip/${str}`;
90
+ } break;
91
+
92
+ // To make "go to definition" work,
93
+ // We have to resolve the actual file system path from virtual path
94
+ // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
95
+ case `coc-nvim`: {
96
+ str = normalize(resolved).replace(/\.zip\//, `.zip::`);
97
+ str = resolve(`zipfile:${str}`);
98
+ } break;
99
+
100
+ // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
101
+ // We have to resolve the actual file system path from virtual path,
102
+ // everything else is up to neovim
103
+ case `neovim`: {
104
+ str = normalize(resolved).replace(/\.zip\//, `.zip::`);
105
+ str = `zipfile://${str}`;
106
+ } break;
107
+
108
+ default: {
109
+ str = `zip:${str}`;
110
+ } break;
111
+ }
112
+ }
113
+ }
114
+
115
+ return str;
116
+ }
117
+
118
+ function fromEditorPath(str) {
119
+ switch (hostInfo) {
120
+ case `coc-nvim`: {
121
+ str = str.replace(/\.zip::/, `.zip/`);
122
+ // The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
123
+ // So in order to convert it back, we use .* to match all the thing
124
+ // before `zipfile:`
125
+ return process.platform === `win32`
126
+ ? str.replace(/^.*zipfile:\//, ``)
127
+ : str.replace(/^.*zipfile:/, ``);
128
+ } break;
129
+
130
+ case `neovim`: {
131
+ str = str.replace(/\.zip::/, `.zip/`);
132
+ // The path for neovim is in format of zipfile:///<pwd>/.yarn/...
133
+ return str.replace(/^zipfile:\/\//, ``);
134
+ } break;
135
+
136
+ case `vscode`:
137
+ default: {
138
+ return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
139
+ } break;
140
+ }
141
+ }
142
+
143
+ // Force enable 'allowLocalPluginLoads'
144
+ // TypeScript tries to resolve plugins using a path relative to itself
145
+ // which doesn't work when using the global cache
146
+ // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
147
+ // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
148
+ // TypeScript already does local loads and if this code is running the user trusts the workspace
149
+ // https://github.com/microsoft/vscode/issues/45856
150
+ const ConfiguredProject = tsserver.server.ConfiguredProject;
151
+ const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
152
+ ConfiguredProject.prototype.enablePluginsWithOptions = function() {
153
+ this.projectService.allowLocalPluginLoads = true;
154
+ return originalEnablePluginsWithOptions.apply(this, arguments);
155
+ };
156
+
157
+ // And here is the point where we hijack the VSCode <-> TS communications
158
+ // by adding ourselves in the middle. We locate everything that looks
159
+ // like an absolute path of ours and normalize it.
160
+
161
+ const Session = tsserver.server.Session;
162
+ const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
163
+ let hostInfo = `unknown`;
164
+
165
+ Object.assign(Session.prototype, {
166
+ onMessage(/** @type {string | object} */ message) {
167
+ const isStringMessage = typeof message === 'string';
168
+ const parsedMessage = isStringMessage ? JSON.parse(message) : message;
169
+
170
+ if (
171
+ parsedMessage != null &&
172
+ typeof parsedMessage === `object` &&
173
+ parsedMessage.arguments &&
174
+ typeof parsedMessage.arguments.hostInfo === `string`
175
+ ) {
176
+ hostInfo = parsedMessage.arguments.hostInfo;
177
+ if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
178
+ const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
179
+ // The RegExp from https://semver.org/ but without the caret at the start
180
+ /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
181
+ ) ?? []).map(Number)
182
+
183
+ if (major === 1) {
184
+ if (minor < 61) {
185
+ hostInfo += ` <1.61`;
186
+ } else if (minor < 66) {
187
+ hostInfo += ` <1.66`;
188
+ } else if (minor < 68) {
189
+ hostInfo += ` <1.68`;
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
196
+ return typeof value === 'string' ? fromEditorPath(value) : value;
197
+ });
198
+
199
+ return originalOnMessage.call(
200
+ this,
201
+ isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
202
+ );
203
+ },
204
+
205
+ send(/** @type {any} */ msg) {
206
+ return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
207
+ return typeof value === `string` ? toEditorPath(value) : value;
208
+ })));
209
+ }
210
+ });
211
+
212
+ return tsserver;
213
+ };
214
+
215
+ if (existsSync(absPnpApiPath)) {
216
+ if (!process.versions.pnp) {
217
+ // Setup the environment to be able to require typescript/lib/tsserverlibrary.js
218
+ require(absPnpApiPath).setup();
219
+ }
220
+ }
221
+
222
+ // Defer to the real typescript/lib/tsserverlibrary.js your application uses
223
+ module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {existsSync} = require(`fs`);
4
+ const {createRequire} = require(`module`);
5
+ const {resolve} = require(`path`);
6
+
7
+ const relPnpApiPath = "../../../../.pnp.cjs";
8
+
9
+ const absPnpApiPath = resolve(__dirname, relPnpApiPath);
10
+ const absRequire = createRequire(absPnpApiPath);
11
+
12
+ if (existsSync(absPnpApiPath)) {
13
+ if (!process.versions.pnp) {
14
+ // Setup the environment to be able to require typescript/lib/typescript.js
15
+ require(absPnpApiPath).setup();
16
+ }
17
+ }
18
+
19
+ // Defer to the real typescript/lib/typescript.js your application uses
20
+ module.exports = absRequire(`typescript/lib/typescript.js`);
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "typescript",
3
+ "version": "4.9.4-sdk",
4
+ "main": "./lib/typescript.js",
5
+ "type": "commonjs"
6
+ }
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- [![TypeScript version][ts-badge]][typescript-4-0]
1
+ [![TypeScript version][ts-badge]][typescript-4-9]
2
2
  [![Node.js version][nodejs-badge]][nodejs]
3
- [![APLv2][license-badge]][license]
4
-
3
+ [![MIT][license-badge]][license]
4
+ [![Node.js CI][gha-badge]][gha-ci]
5
5
  # Font Range
6
6
 
7
7
  | ![NJ](https://raw.githubusercontent.com/black7375/font-range/master/resource/News_Japanese.gif) | ![NK](https://raw.githubusercontent.com/black7375/font-range/master/resource/News_Korean.gif) | ![NC](https://raw.githubusercontent.com/black7375/font-range/master/resource/News_Chinese.gif) |
@@ -17,47 +17,41 @@ Google Font provides a subset of [Korean](https://design.google/news/google-font
17
17
  ![Result](https://raw.githubusercontent.com/black7375/font-range/master/resource/Korean_Japanese.png)
18
18
 
19
19
  ## Usage
20
- Google font `CSS file`(include `unicode-range` file) url and `font path` are fine.
21
-
22
- ```js
23
- fontRange(google_font_css_url, font_path);
24
- fontRange(google_font_css_url, font_path, save_path); // Option1
25
- fontRange(google_font_css_url, font_path, {
26
- savePath: "<SAVE SUBSET PATH>",
27
- format: "<FONT FORMAT>",
28
- nameForamt: "<NAME FORAMT>",
29
- defaultArgs: "<Default Args>",
30
- etcArgs: "<ETC pyftsubset args>"
31
- }); // Option2
32
- ```
33
- - `save_path`'s default: `<font_path>`
34
- - `format`'s default: `"woff2"`
35
- - `nameFormat`'s default: `"{NAME}_{INDEX}{EXT}"`
36
- - `defaultArgs`'s default:
37
- ```
38
- "--layout-features='*' \
39
- --glyph-names \
40
- --symbol-cmap \
41
- --legacy-cmap \
42
- --notdef-glyph \
43
- --notdef-outline \
44
- --recommended-glyphs \
45
- --name-legacy \
46
- --drop-tables= \
47
- --name-IDs='*' \
48
- --name-languages='*'
49
- "
50
- ```
51
- - `etcArgs`'s default: `""`
52
-
53
20
  ### Requires
54
21
  It has dependencies on the following packages:
55
22
 
56
23
  ```sh
57
- pip install fonttools[ufo,woff,unicode] zopfli brotli
24
+ pip install fonttools[ufo,woff,unicode] zopfli brotli
58
25
  ```
59
26
 
60
- ### CSS URL?
27
+ ### Basics
28
+ This project has three types.
29
+ - `fontRange()`: Subset based on `unicode-range` in the CSS file.
30
+ - `fontSubset()`: Subset based on text or text file.
31
+ - `fontPipe()`: Use `fontRange()` and `fontSubset()` to perform multiple subset operations.
32
+
33
+ ```js
34
+ // fontRange
35
+ fontRange(font_path, css_url_or_path);
36
+ fontRange(font_path, css_url_or_path, save_dir); // Option1
37
+ fontRange(font_path, css_url_or_path, { ...options }); // Option2
38
+
39
+ // fontSubset
40
+ fontRange(font_path);
41
+ fontRange(font_path, save_dir); // Option1
42
+ fontRange(font_path, { ...options }); // Option2
43
+
44
+ // fontPipe
45
+ fontPipe([
46
+ { font_path }, // As `fontSubset(font_path)`
47
+ { font_path, option: { text: "abc" } }, // As `fontSubset(font_path, { text: "abc" })`
48
+ { font_path, option: { textFile: file_path } }, // As `fontSubset(font_path, { textFile: file_path })`
49
+ { font_path, option: { cssFile: css_url_or_path } } // As `fontRange(font_path, css_url_or_path)`
50
+ ]);
51
+ fontPipe([{ font_path1 }, { font_path2 }], "<index>/<total>"); // Sharding option use like `1/2`
52
+ ```
53
+
54
+ #### CSS URL?
61
55
  The URL of [`Noto Sans`](https://www.google.com/get/noto/) is included in the package.
62
56
 
63
57
  ![Noto](https://raw.githubusercontent.com/black7375/font-range/master/resource/Noto_0.png)
@@ -72,13 +66,117 @@ const targets = {
72
66
  };
73
67
  ```
74
68
 
69
+ ### Default Options
70
+
71
+ List of options available for all function options.
72
+
73
+ ```ts
74
+ type Format = "otf" | "ttf" | "woff2" | "woff" | "woff-zopfli";
75
+ interface FontDefaultOptionI {
76
+ saveDir: string; // Directory to save the generated subset or downloaded CSS
77
+ format: Format; // Subset type to create
78
+ nameFormat: string; // File name format to create
79
+ logFormat: string; // Log format to print
80
+ defaultArgs: string[]; // `pyftsubset` option - default
81
+ etcArgs: string[]; // `pyftsubset` option - for users
82
+ }
83
+ ```
84
+ - `save_dir`'s default: `<font_path>`
85
+ - `format`'s default: `"woff2"`
86
+ - `nameFormat`'s default: `"{NAME}_{INDEX}{EXT}"`
87
+ - `defaultArgs`'s default:
88
+ ```js
89
+ [
90
+ "--layout-features=*",
91
+ "--glyph-names",
92
+ "--symbol-cmap",
93
+ "--legacy-cmap",
94
+ "--notdef-glyph",
95
+ "--notdef-outline",
96
+ "--recommended-glyphs",
97
+ "--name-legacy",
98
+ "--drop-tables=",
99
+ "--name-IDs=*",
100
+ "--name-languages=*"
101
+ ]
102
+ ```
103
+ - `etcArgs`'s default: `[]`
104
+
105
+ ### Font Range
106
+
107
+ It is designed to be able to do a subset using `unicode-range` of CSS.
108
+
109
+ #### Option
110
+
111
+ The name of the generated file can be determined from the CSS.
112
+
113
+ ```ts
114
+ interface FontRangeOptionI extends FontDefaultOptionI {
115
+ fromCSS: "default" | "srcIndex" | "srcName";
116
+ }
117
+ ```
118
+ - `default`: The `index` of the file name increases in the generated order
119
+ - `srcIndex`: The `index` of the file name uses [`src`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src) in CSS [#9](https://github.com/black7375/font-range/issues/9)
120
+ - Based on the first `url()`
121
+ - `srcName`: The file name uses [`src`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src) in CSS
122
+ - Based on the first `url()`
123
+
124
+ ### Font Subset
125
+
126
+ It is designed to be able to do a general subset.
127
+
128
+ #### Option
129
+
130
+ By default, all letters are included, but you can set the letters to include:
131
+
132
+ ```ts
133
+ interface FontSubsetOptionI extends FontDefaultOptionI {
134
+ textFile: string; // From text file
135
+ text: string; // Letter like `abc`
136
+ }
137
+ ```
138
+
139
+ ### Font Pipe
140
+
141
+ It offers a simple API when doing a large amount of subsets.
142
+
143
+ Performance is optimized using worker poll and provides sharding for distributed environments.
144
+
145
+ #### Option
146
+
147
+ If `cssFile` has attributes, it is recognized as `fontRange()`.
148
+
149
+ ```ts
150
+ interface FontPipeOptionI extends FontRangeOptionI, FontSubsetOptionI {
151
+ cssFile: string;
152
+ }
153
+ ```
154
+
155
+ #### Sharding
156
+
157
+ You can control sharing using `argument` or `environment variable`.
158
+ If both values are used together, `argument` is applied first.
159
+
160
+ - Argument: Explicitly used through function.
161
+ ```js
162
+ fontPipe([{ font_path1 }, { font_path2 }], "<index>/<total>");
163
+ ```
164
+
165
+ - Environment Variable: Make it easy to use in CI, npm scripts, ..etc.
166
+ ```sh
167
+ SHARD=<index>/total
168
+ node subset.js
169
+ ```
170
+
75
171
  ## License
76
172
 
77
- Licensed under the APLv2. See the [LICENSE](https://github.com/jsynowiec/node-typescript-boilerplate/blob/master/LICENSE) file for details.
173
+ Licensed under the MIT. See the [LICENSE][license] file for details.
78
174
 
79
- [ts-badge]: https://img.shields.io/badge/TypeScript-4.0-blue.svg
80
- [nodejs-badge]: https://img.shields.io/badge/Node.js->=%2012.13-blue.svg
81
- [nodejs]: https://nodejs.org/dist/latest-v12.x/docs/api/
82
- [typescript-4-0]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html
175
+ [ts-badge]: https://img.shields.io/badge/TypeScript-4.9-blue.svg
176
+ [typescript-4-9]: https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/
177
+ [nodejs-badge]: https://img.shields.io/badge/Node.js->=%2016.16-blue.svg
178
+ [nodejs]: https://nodejs.org/dist/latest-v18.x/docs/api/
83
179
  [license-badge]: https://img.shields.io/badge/license-MIT-blue
84
180
  [license]: https://github.com/black7375/font-range/blob/master/LICENSE
181
+ [gha-badge]: https://github.com/black7375/font-range/actions/workflows/nodejs.yml/badge.svg?branch=master
182
+ [gha-ci]: https://github.com/black7375/font-range/actions/workflows/nodejs.yml