Test that typedoc builds with no warnings

This commit is contained in:
Natalie Weizenbaum 2021-09-29 18:55:41 -07:00
parent 1b0574a27a
commit f289bb8c9b
18 changed files with 302 additions and 157 deletions

View File

@ -1,3 +1,4 @@
{ {
"extends": "./node_modules/gts/" "extends": "./node_modules/gts/",
"ignorePatterns": ["/docs/**"]
} }

2
.gitignore vendored
View File

@ -88,3 +88,5 @@ typings/
.dynamodb/ .dynamodb/
# End of https://www.gitignore.io/api/node # End of https://www.gitignore.io/api/node
/docs

View File

@ -1,21 +1,15 @@
import {URL} from 'url'; import {URL} from 'url';
import {Syntax} from './options'; import {Syntax} from './options';
import {PromiseOr} from './util/promise_or';
interface SyncFileImporter { export interface FileImporter<
sync extends 'sync' | 'async' = 'sync' | 'async'
> {
findFileUrl( findFileUrl(
url: string, url: string,
options: {fromImport: boolean} options: {fromImport: boolean}
): FileImporterResult | null; ): PromiseOr<FileImporterResult | null, sync>;
canonicalize?: never;
}
interface AsyncFileImporter {
findFileUrl(
url: string,
options: {fromImport: boolean}
): Promise<FileImporterResult | null> | FileImporterResult | null;
canonicalize?: never; canonicalize?: never;
} }
@ -26,21 +20,13 @@ export interface FileImporterResult {
sourceMapUrl?: URL; sourceMapUrl?: URL;
} }
interface SyncImporter { export interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
canonicalize(url: string, options: {fromImport: boolean}): URL | null;
load(canonicalUrl: URL): ImporterResult | null;
findFileUrl?: never;
}
interface AsyncImporter {
canonicalize( canonicalize(
url: string, url: string,
options: {fromImport: boolean} options: {fromImport: boolean}
): Promise<URL | null> | URL | null; ): PromiseOr<URL | null, sync>;
load( load(canonicalUrl: URL): PromiseOr<ImporterResult | null, sync>;
canonicalUrl: URL
): Promise<ImporterResult | null> | ImporterResult | null;
findFileUrl?: never; findFileUrl?: never;
} }
@ -52,11 +38,3 @@ export interface ImporterResult {
sourceMapUrl?: URL; sourceMapUrl?: URL;
} }
export type FileImporter<sync extends 'sync' | 'async'> = sync extends 'async'
? AsyncFileImporter
: SyncFileImporter;
export type Importer<sync extends 'sync' | 'async'> = sync extends 'async'
? AsyncImporter
: SyncImporter;

24
js-api-doc/index.d.ts vendored
View File

@ -24,6 +24,7 @@ export {
StringOptions, StringOptions,
Syntax, Syntax,
} from './options'; } from './options';
export {PromiseOr} from './util/promise_or';
export { export {
ListSeparator, ListSeparator,
SassArgumentList, SassArgumentList,
@ -42,9 +43,26 @@ export {
// Legacy APIs // Legacy APIs
export {LegacyException} from './legacy/exception'; export {LegacyException} from './legacy/exception';
export {LegacyFunction, LegacyValue, types} from './legacy/function'; export {
export {LegacyImporter} from './legacy/importer'; LegacyAsyncFunction,
export {LegacyOptions} from './legacy/options'; LegacySyncFunction,
LegacyFunction,
LegacyValue,
types,
} from './legacy/function';
export {
ImporterThis,
LegacyAsyncImporter,
LegacySyncImporter,
LegacyImporter,
} from './legacy/importer';
export {
LegacySharedOptions,
LegacyFileOptions,
LegacyStringOptions,
LegacyOptions,
} from './legacy/options';
export {PluginThis} from './legacy/plugin_this';
export {LegacyResult, render, renderSync} from './legacy/render'; export {LegacyResult, render, renderSync} from './legacy/render';
export const info: string; export const info: string;

View File

@ -1,15 +1,18 @@
import {PluginThis} from './plugin_this'; import {PluginThis} from './plugin_this';
type _SyncFunction = (this: PluginThis, ...args: LegacyValue[]) => LegacyValue; export type LegacySyncFunction = (
this: PluginThis,
...args: LegacyValue[]
) => LegacyValue;
type _AsyncFunction = ( export type LegacyAsyncFunction = (
this: PluginThis, this: PluginThis,
...args: [...LegacyValue[], (type: LegacyValue) => void] ...args: [...LegacyValue[], (type: LegacyValue) => void]
) => void; ) => void;
export type LegacyFunction<sync = 'sync' | 'async'> = export type LegacyFunction<sync extends 'sync' | 'async'> = sync extends 'async'
| _SyncFunction ? LegacySyncFunction | LegacyAsyncFunction
| (sync extends 'async' ? _AsyncFunction : never); : LegacySyncFunction;
export type LegacyValue = export type LegacyValue =
| types.Null | types.Null

View File

@ -4,19 +4,19 @@ interface ImporterThis extends PluginThis {
fromImport: boolean; fromImport: boolean;
} }
type _SyncImporter = ( type LegacySyncImporter = (
this: ImporterThis, this: ImporterThis,
url: string, url: string,
prev: string prev: string
) => {file: string} | {contents: string}; ) => {file: string} | {contents: string};
type _AsyncImporter = ( type LegacyAsyncImporter = (
this: ImporterThis, this: ImporterThis,
url: string, url: string,
prev: string, prev: string,
done: (data: {file: string} | {contents: string} | Error) => void done: (data: {file: string} | {contents: string} | Error) => void
) => void; ) => void;
export type LegacyImporter<sync = 'sync' | 'async'> = export type LegacyImporter<sync = 'sync' | 'async'> = sync extends 'async'
| _SyncImporter ? LegacySyncImporter | LegacyAsyncImporter
| (sync extends 'async' ? _AsyncImporter : never); : LegacySyncImporter;

View File

@ -7,7 +7,7 @@ import {LegacyFunction} from './function';
* This is only exported so that it can be modified by proposals for new * This is only exported so that it can be modified by proposals for new
* features. It should not be referred to by user code. * features. It should not be referred to by user code.
*/ */
export interface _Options<sync = 'sync' | 'async'> { export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
includePaths?: string[]; includePaths?: string[];
indentedSyntax?: boolean; indentedSyntax?: boolean;
indentType?: 'space' | 'tab'; indentType?: 'space' | 'tab';
@ -32,13 +32,17 @@ export interface _Options<sync = 'sync' | 'async'> {
logger?: Logger; logger?: Logger;
} }
export type LegacyOptions<sync = 'sync' | 'async'> = _Options<sync> & export interface LegacyFileOptions<sync extends 'sync' | 'async'>
( extends LegacySharedOptions<sync> {
| { file: string;
file: string; }
}
| { export interface LegacyStringOptions<sync extends 'sync' | 'async'>
data: string; extends LegacySharedOptions<sync> {
file?: string; data: string;
} file?: string;
); }
export type LegacyOptions<sync extends 'sync' | 'async'> =
| LegacyFileOptions<sync>
| LegacySharedOptions<sync>;

View File

@ -3,18 +3,15 @@ import {URL} from 'url';
import {FileImporter, Importer} from './importer'; import {FileImporter, Importer} from './importer';
import {Logger} from './logger'; import {Logger} from './logger';
import {Value} from './value'; import {Value} from './value';
import {PromiseOr} from './util/promise_or';
export type Syntax = 'scss' | 'indented' | 'css'; export type Syntax = 'scss' | 'indented' | 'css';
export type OutputStyle = 'expanded' | 'compressed'; export type OutputStyle = 'expanded' | 'compressed';
export type CustomFunction<sync extends 'sync' | 'async'> = sync extends 'sync' export type CustomFunction<sync extends 'sync' | 'async'> = (
? (args: Value[]) => Value args: Value[]
: (args: Value[]) => Value | Promise<Value>; ) => PromiseOr<Value, sync>;
type _Importer<sync extends 'sync' | 'async'> =
| Importer<sync>
| FileImporter<sync>;
export interface Options<sync extends 'sync' | 'async'> { export interface Options<sync extends 'sync' | 'async'> {
alertAscii?: boolean; alertAscii?: boolean;
@ -23,7 +20,7 @@ export interface Options<sync extends 'sync' | 'async'> {
functions?: Record<string, CustomFunction<sync>>; functions?: Record<string, CustomFunction<sync>>;
importers?: _Importer<sync>[]; importers?: (Importer<sync> | FileImporter<sync>)[];
loadPaths?: string[]; loadPaths?: string[];
@ -45,7 +42,7 @@ export type StringOptions<sync extends 'sync' | 'async'> = Options<sync> & {
url?: URL; url?: URL;
} }
| { | {
importer: _Importer<sync>; importer: Importer<sync> | FileImporter<sync>;
url: URL; url: URL;
} }
); );

7
js-api-doc/util/promise_or.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
/**
* A utility type for choosing between synchronous and asynchronous return
* values.
*/
export type PromiseOr<T, sync extends 'sync' | 'async'> = sync extends 'sync'
? T
: T | Promise<T>;

148
package-lock.json generated
View File

@ -19,7 +19,8 @@
"prettier": "^2.4.1", "prettier": "^2.4.1",
"source-map-js": "^0.6.2", "source-map-js": "^0.6.2",
"strip-comments": "^2.0.1", "strip-comments": "^2.0.1",
"ts-node": "^10.2.1" "ts-node": "^10.2.1",
"typedoc": "^0.22.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^14.11.2", "@types/node": "^14.11.2",
@ -2673,6 +2674,11 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/jsonc-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA=="
},
"node_modules/jsprim": { "node_modules/jsprim": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@ -2852,6 +2858,11 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="
},
"node_modules/make-dir": { "node_modules/make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@ -3266,6 +3277,27 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/onigasm": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/onigasm/-/onigasm-2.2.5.tgz",
"integrity": "sha512-F+th54mPc0l1lp1ZcFMyL/jTs2Tlq4SqIHKIXGZOR/VkHkF9A7Fr5rRr5+ZG/lWeRsyrClLYRq7s/yFQ/XhWCA==",
"dependencies": {
"lru-cache": "^5.1.1"
}
},
"node_modules/onigasm/node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dependencies": {
"yallist": "^3.0.2"
}
},
"node_modules/onigasm/node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.1", "version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@ -4036,6 +4068,16 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/shiki": {
"version": "0.9.11",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.11.tgz",
"integrity": "sha512-tjruNTLFhU0hruCPoJP0y+B9LKOmcqUhTpxn7pcJB3fa+04gFChuEmxmrUfOJ7ZO6Jd+HwMnDHgY3lv3Tqonuw==",
"dependencies": {
"jsonc-parser": "^3.0.0",
"onigasm": "^2.2.5",
"vscode-textmate": "5.2.0"
}
},
"node_modules/signal-exit": { "node_modules/signal-exit": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@ -4507,6 +4549,38 @@
"is-typedarray": "^1.0.0" "is-typedarray": "^1.0.0"
} }
}, },
"node_modules/typedoc": {
"version": "0.22.4",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.4.tgz",
"integrity": "sha512-M/a8NnPxq3/iZNNVjzFCK5gu4m//HTJIPbSS0JQVbkHJPP9wyepR12agylWTSqeVZe0xsbidVtO26+PP7iD/jw==",
"dependencies": {
"glob": "^7.1.7",
"lunr": "^2.3.9",
"marked": "^3.0.4",
"minimatch": "^3.0.4",
"shiki": "^0.9.11"
},
"bin": {
"typedoc": "bin/typedoc"
},
"engines": {
"node": ">= 12.10.0"
},
"peerDependencies": {
"typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x"
}
},
"node_modules/typedoc/node_modules/marked": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/marked/-/marked-3.0.4.tgz",
"integrity": "sha512-jBo8AOayNaEcvBhNobg6/BLhdsK3NvnKWJg33MAAPbvTWiG4QBn9gpW1+7RssrKu4K1dKlN+0goVQwV41xEfOA==",
"bin": {
"marked": "bin/marked"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.3.5", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
@ -4622,6 +4696,11 @@
"extsprintf": "^1.2.0" "extsprintf": "^1.2.0"
} }
}, },
"node_modules/vscode-textmate": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
"integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ=="
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -6714,6 +6793,11 @@
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
}, },
"jsonc-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA=="
},
"jsprim": { "jsprim": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@ -6866,6 +6950,11 @@
"yallist": "^4.0.0" "yallist": "^4.0.0"
} }
}, },
"lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="
},
"make-dir": { "make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@ -7177,6 +7266,29 @@
"mimic-fn": "^2.1.0" "mimic-fn": "^2.1.0"
} }
}, },
"onigasm": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/onigasm/-/onigasm-2.2.5.tgz",
"integrity": "sha512-F+th54mPc0l1lp1ZcFMyL/jTs2Tlq4SqIHKIXGZOR/VkHkF9A7Fr5rRr5+ZG/lWeRsyrClLYRq7s/yFQ/XhWCA==",
"requires": {
"lru-cache": "^5.1.1"
},
"dependencies": {
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"requires": {
"yallist": "^3.0.2"
}
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
"optionator": { "optionator": {
"version": "0.9.1", "version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@ -7734,6 +7846,16 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true "dev": true
}, },
"shiki": {
"version": "0.9.11",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.11.tgz",
"integrity": "sha512-tjruNTLFhU0hruCPoJP0y+B9LKOmcqUhTpxn7pcJB3fa+04gFChuEmxmrUfOJ7ZO6Jd+HwMnDHgY3lv3Tqonuw==",
"requires": {
"jsonc-parser": "^3.0.0",
"onigasm": "^2.2.5",
"vscode-textmate": "5.2.0"
}
},
"signal-exit": { "signal-exit": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@ -8085,6 +8207,25 @@
"is-typedarray": "^1.0.0" "is-typedarray": "^1.0.0"
} }
}, },
"typedoc": {
"version": "0.22.4",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.4.tgz",
"integrity": "sha512-M/a8NnPxq3/iZNNVjzFCK5gu4m//HTJIPbSS0JQVbkHJPP9wyepR12agylWTSqeVZe0xsbidVtO26+PP7iD/jw==",
"requires": {
"glob": "^7.1.7",
"lunr": "^2.3.9",
"marked": "^3.0.4",
"minimatch": "^3.0.4",
"shiki": "^0.9.11"
},
"dependencies": {
"marked": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/marked/-/marked-3.0.4.tgz",
"integrity": "sha512-jBo8AOayNaEcvBhNobg6/BLhdsK3NvnKWJg33MAAPbvTWiG4QBn9gpW1+7RssrKu4K1dKlN+0goVQwV41xEfOA=="
}
}
},
"typescript": { "typescript": {
"version": "4.3.5", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
@ -8174,6 +8315,11 @@
"extsprintf": "^1.2.0" "extsprintf": "^1.2.0"
} }
}, },
"vscode-textmate": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
"integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ=="
},
"which": { "which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -13,8 +13,9 @@
"toc-check": "npx ts-node test/toc-check.ts", "toc-check": "npx ts-node test/toc-check.ts",
"update-toc": "npx ts-node tool/update-toc.ts", "update-toc": "npx ts-node tool/update-toc.ts",
"js-api-doc-check": "npx ts-node test/js-api-doc-check.ts", "js-api-doc-check": "npx ts-node test/js-api-doc-check.ts",
"typedoc": "npx typedoc --treatWarningsAsErrors js-api-doc/index.d.ts",
"fix": "gts fix", "fix": "gts fix",
"test": "gts lint && tsc --noEmit && npm run toc-check && npm run link-check && npm run js-api-doc-check" "test": "gts lint && tsc --noEmit && npm run toc-check && npm run link-check && npm run js-api-doc-check && npm run typedoc"
}, },
"dependencies": { "dependencies": {
"@types/diff": "^5.0.1", "@types/diff": "^5.0.1",
@ -30,7 +31,8 @@
"prettier": "^2.4.1", "prettier": "^2.4.1",
"source-map-js": "^0.6.2", "source-map-js": "^0.6.2",
"strip-comments": "^2.0.1", "strip-comments": "^2.0.1",
"ts-node": "^10.2.1" "ts-node": "^10.2.1",
"typedoc": "^0.22.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^14.11.2", "@types/node": "^14.11.2",

View File

@ -1,6 +1,7 @@
import {URL} from 'url'; import {URL} from 'url';
import {Syntax} from './options'; import {Syntax} from './options';
import {PromiseOr} from './util/promise_or';
/** /**
* This interface represents an [importer]. When the importer is invoked with a * This interface represents an [importer]. When the importer is invoked with a
@ -12,7 +13,8 @@ import {Syntax} from './options';
* and `false` otherwise. * and `false` otherwise.
* *
* - Let `url` be the result of calling `findFileUrl` with `url` and * - Let `url` be the result of calling `findFileUrl` with `url` and
* `fromImport`. * `fromImport`. If it returns a promise, wait for it to complete and use its
* value instead, or rethrow its error if it rejects.
* *
* - If `url` is null, return null. * - If `url` is null, return null.
* *
@ -36,26 +38,13 @@ import {Syntax} from './options';
* *
* [resolving `url`]: ../spec/modules.md#resolving-a-file-url * [resolving `url`]: ../spec/modules.md#resolving-a-file-url
*/ */
interface SyncFileImporter { export interface FileImporter<
sync extends 'sync' | 'async' = 'sync' | 'async'
> {
findFileUrl( findFileUrl(
url: string, url: string,
options: {fromImport: boolean} options: {fromImport: boolean}
): FileImporterResult | null; ): PromiseOr<FileImporterResult | null, sync>;
canonicalize?: never;
}
/**
* This interface represents an [importer]. It has the same behavior as
* `SyncFileImporter`, except that if `findFileUrl` returns a `Promise` it waits
* for it to complete and uses its value as the return value. If a `Promise`
* emits an error, it rethrows that error.
*/
interface AsyncFileImporter {
findFileUrl(
url: string,
options: {fromImport: boolean}
): Promise<FileImporterResult | null> | FileImporterResult | null;
canonicalize?: never; canonicalize?: never;
} }
@ -93,11 +82,14 @@ export interface FileImporterResult {
* and `false` otherwise. * and `false` otherwise.
* *
* - Let `url` be the result of calling `canonicalize` with `url` and * - Let `url` be the result of calling `canonicalize` with `url` and
* `fromImport`. * `fromImport`. If it returns a promise, wait for it to complete and use its
* value instead, or rethrow its error if it rejects.
* *
* - If `url` is null, return null. * - If `url` is null, return null.
* *
* - Let `result` be the result of calling `load` with `url`. * - Let `result` be the result of calling `load` with `url`. If it returns a
* promise, wait for it to complete and use its value instead, or rethrow its
* error if it rejects.
* *
* - If `result` is null, return null. * - If `result` is null, return null.
* *
@ -111,27 +103,13 @@ export interface FileImporterResult {
* *
* [resolving `url`]: ../spec/modules.md#resolving-a-file-url * [resolving `url`]: ../spec/modules.md#resolving-a-file-url
*/ */
interface SyncImporter { export interface Importer<sync extends 'sync' | 'async' = 'sync' | 'async'> {
canonicalize(url: string, options: {fromImport: boolean}): URL | null;
load(canonicalUrl: URL): ImporterResult | null;
findFileUrl?: never;
}
/**
* This interface represents an [importer]. It has the same behavior as
* `SyncImporter`, except that if `canonicalize` or `load` return a `Promise` it
* waits for it to complete and uses its value as the return value. If a
* `Promise` emits an error, it rethrows that error.
*/
interface AsyncImporter {
canonicalize( canonicalize(
url: string, url: string,
options: {fromImport: boolean} options: {fromImport: boolean}
): Promise<URL | null> | URL | null; ): PromiseOr<URL | null, sync>;
load( load(canonicalUrl: URL): PromiseOr<ImporterResult | null, sync>;
canonicalUrl: URL
): Promise<ImporterResult | null> | ImporterResult | null;
findFileUrl?: never; findFileUrl?: never;
} }
@ -152,19 +130,3 @@ export interface ImporterResult {
*/ */
sourceMapUrl?: URL; sourceMapUrl?: URL;
} }
/**
* > This type is exported so that TypeScript users can explicitly write a class
* > that `implements FileImporter`.
*/
export type FileImporter<sync extends 'sync' | 'async'> = sync extends 'async'
? AsyncFileImporter
: SyncFileImporter;
/**
* > This type is exported so that TypeScript users can explicitly write a class
* > that `implements Importer`.
*/
export type Importer<sync extends 'sync' | 'async'> = sync extends 'async'
? AsyncImporter
: SyncImporter;

View File

@ -52,6 +52,7 @@ export {
StringOptions, StringOptions,
Syntax, Syntax,
} from './options'; } from './options';
export {PromiseOr} from './util/promise_or';
export { export {
ListSeparator, ListSeparator,
SassArgumentList, SassArgumentList,
@ -70,9 +71,26 @@ export {
// Legacy APIs // Legacy APIs
export {LegacyException} from './legacy/exception'; export {LegacyException} from './legacy/exception';
export {LegacyFunction, LegacyValue, types} from './legacy/function'; export {
export {LegacyImporter} from './legacy/importer'; LegacyAsyncFunction,
export {LegacyOptions} from './legacy/options'; LegacySyncFunction,
LegacyFunction,
LegacyValue,
types,
} from './legacy/function';
export {
ImporterThis,
LegacyAsyncImporter,
LegacySyncImporter,
LegacyImporter,
} from './legacy/importer';
export {
LegacySharedOptions,
LegacyFileOptions,
LegacyStringOptions,
LegacyOptions,
} from './legacy/options';
export {PluginThis} from './legacy/plugin_this';
export {LegacyResult, render, renderSync} from './legacy/render'; export {LegacyResult, render, renderSync} from './legacy/render';
/** /**

View File

@ -1,15 +1,18 @@
import {PluginThis} from './plugin_this'; import {PluginThis} from './plugin_this';
type _SyncFunction = (this: PluginThis, ...args: LegacyValue[]) => LegacyValue; export type LegacySyncFunction = (
this: PluginThis,
...args: LegacyValue[]
) => LegacyValue;
type _AsyncFunction = ( export type LegacyAsyncFunction = (
this: PluginThis, this: PluginThis,
...args: [...LegacyValue[], (type: LegacyValue) => void] ...args: [...LegacyValue[], (type: LegacyValue) => void]
) => void; ) => void;
export type LegacyFunction<sync = 'sync' | 'async'> = export type LegacyFunction<sync extends 'sync' | 'async'> = sync extends 'async'
| _SyncFunction ? LegacySyncFunction | LegacyAsyncFunction
| (sync extends 'async' ? _AsyncFunction : never); : LegacySyncFunction;
export type LegacyValue = export type LegacyValue =
| types.Null | types.Null

View File

@ -15,19 +15,19 @@ interface ImporterThis extends PluginThis {
fromImport: boolean; fromImport: boolean;
} }
type _SyncImporter = ( type LegacySyncImporter = (
this: ImporterThis, this: ImporterThis,
url: string, url: string,
prev: string prev: string
) => {file: string} | {contents: string}; ) => {file: string} | {contents: string};
type _AsyncImporter = ( type LegacyAsyncImporter = (
this: ImporterThis, this: ImporterThis,
url: string, url: string,
prev: string, prev: string,
done: (data: {file: string} | {contents: string} | Error) => void done: (data: {file: string} | {contents: string} | Error) => void
) => void; ) => void;
export type LegacyImporter<sync = 'sync' | 'async'> = export type LegacyImporter<sync = 'sync' | 'async'> = sync extends 'async'
| _SyncImporter ? LegacySyncImporter | LegacyAsyncImporter
| (sync extends 'async' ? _AsyncImporter : never); : LegacySyncImporter;

View File

@ -9,7 +9,7 @@ import {LegacyFunction} from './function';
* This is only exported so that it can be modified by proposals for new * This is only exported so that it can be modified by proposals for new
* features. It should not be referred to by user code. * features. It should not be referred to by user code.
*/ */
export interface _Options<sync = 'sync' | 'async'> { export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
includePaths?: string[]; includePaths?: string[];
indentedSyntax?: boolean; indentedSyntax?: boolean;
indentType?: 'space' | 'tab'; indentType?: 'space' | 'tab';
@ -66,13 +66,17 @@ export interface _Options<sync = 'sync' | 'async'> {
logger?: Logger; logger?: Logger;
} }
export type LegacyOptions<sync = 'sync' | 'async'> = _Options<sync> & export interface LegacyFileOptions<sync extends 'sync' | 'async'>
( extends LegacySharedOptions<sync> {
| { file: string;
file: string; }
}
| { export interface LegacyStringOptions<sync extends 'sync' | 'async'>
data: string; extends LegacySharedOptions<sync> {
file?: string; data: string;
} file?: string;
); }
export type LegacyOptions<sync extends 'sync' | 'async'> =
| LegacyFileOptions<sync>
| LegacySharedOptions<sync>;

View File

@ -3,6 +3,7 @@ import {URL} from 'url';
import {FileImporter, Importer} from './importer'; import {FileImporter, Importer} from './importer';
import {Logger} from './logger'; import {Logger} from './logger';
import {Value} from './value'; import {Value} from './value';
import {PromiseOr} from './util/promise_or';
/** The types of input syntax that the compiler can parse. */ /** The types of input syntax that the compiler can parse. */
export type Syntax = 'scss' | 'indented' | 'css'; export type Syntax = 'scss' | 'indented' | 'css';
@ -17,17 +18,9 @@ export type Syntax = 'scss' | 'indented' | 'css';
export type OutputStyle = 'expanded' | 'compressed'; export type OutputStyle = 'expanded' | 'compressed';
/** A custom function that can be called from Sass stylesheets. */ /** A custom function that can be called from Sass stylesheets. */
export type CustomFunction<sync extends 'sync' | 'async'> = sync extends 'sync' export type CustomFunction<sync extends 'sync' | 'async'> = (
? (args: Value[]) => Value args: Value[]
: (args: Value[]) => Value | Promise<Value>; ) => PromiseOr<Value, sync>;
/**
* > This type allows options to refer to tersely refer to everything that
* > represents an importer.
*/
type _Importer<sync extends 'sync' | 'async'> =
| Importer<sync>
| FileImporter<sync>;
/** /**
* All of the options for a Sass compilation that are shared by compiling from a * All of the options for a Sass compilation that are shared by compiling from a
@ -64,7 +57,7 @@ export interface Options<sync extends 'sync' | 'async'> {
functions?: Record<string, CustomFunction<sync>>; functions?: Record<string, CustomFunction<sync>>;
/** The list of of custom importers to use to resolve file loads. */ /** The list of of custom importers to use to resolve file loads. */
importers?: _Importer<sync>[]; importers?: (Importer<sync> | FileImporter<sync>)[];
/** If set, the compiler must use these paths to resolve imports. */ /** If set, the compiler must use these paths to resolve imports. */
loadPaths?: string[]; loadPaths?: string[];
@ -132,7 +125,7 @@ export type StringOptions<sync extends 'sync' | 'async'> = Options<sync> & {
} }
| { | {
/** The importer to use to resolve relative imports in the entrypoint. */ /** The importer to use to resolve relative imports in the entrypoint. */
importer: _Importer<sync>; importer: Importer<sync> | FileImporter<sync>;
/** The canonical URL of the entrypoint. */ /** The canonical URL of the entrypoint. */
url: URL; url: URL;
} }

7
spec/js-api/util/promise_or.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
/**
* A utility type for choosing between synchronous and asynchronous return
* values.
*/
export type PromiseOr<T, sync extends 'sync' | 'async'> = sync extends 'sync'
? T
: T | Promise<T>;