mirror of
https://github.com/Shopify/draggable.git
synced 2026-02-01 16:46:56 +00:00
tsdoc switch
This commit is contained in:
parent
a8bfa03cf7
commit
276174bd17
22
.eslintrc.js
22
.eslintrc.js
@ -13,7 +13,9 @@ module.exports = {
|
||||
},
|
||||
rules: {
|
||||
'jest/valid-title': 'off',
|
||||
'tsdoc/syntax': 'warn',
|
||||
},
|
||||
plugins: ['eslint-plugin-tsdoc'],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
@ -24,4 +26,24 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['src/**/*.js', 'src/**/*.ts'],
|
||||
excludedFiles: ['src/**/*.test.js', 'src/**/*.test.ts'],
|
||||
rules: {
|
||||
'require-jsdoc': [
|
||||
'error',
|
||||
{
|
||||
require: {
|
||||
FunctionDeclaration: false,
|
||||
MethodDefinition: true,
|
||||
ClassDeclaration: true,
|
||||
ArrowFunctionExpression: true,
|
||||
FunctionExpression: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"source": "./src",
|
||||
"destination": "./docs",
|
||||
"plugins": [
|
||||
{"name": "esdoc-standard-plugin"},
|
||||
{"name": "esdoc-ecmascript-proposal-plugin", "option": {"all": true}}
|
||||
]
|
||||
}
|
||||
10
package.json
10
package.json
@ -34,7 +34,7 @@
|
||||
"release": "yarn run build:production && changeset publish",
|
||||
"lint": "eslint ./src ./test --max-warnings 0",
|
||||
"type-check": "tsc -b",
|
||||
"esdoc": "esdoc -c esdoc.json",
|
||||
"docs": "typedoc",
|
||||
"test": "jest",
|
||||
"build:development": "yarn rollup --config rollup.development.config.ts --configPlugin @rollup/plugin-typescript",
|
||||
"build:production": "tsc && tsc-alias && yarn rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript && yarn uglifyjs --compress --mangle -- build/umd/index.js -o build/umd/index.min.js",
|
||||
@ -53,6 +53,8 @@
|
||||
"@babel/preset-typescript": "^7.23.0",
|
||||
"@changesets/changelog-github": "^0.4.8",
|
||||
"@changesets/cli": "^2.26.2",
|
||||
"@microsoft/tsdoc": "^0.14.2",
|
||||
"@microsoft/tsdoc-config": "^0.16.2",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-commonjs": "^25.0.4",
|
||||
"@rollup/plugin-node-resolve": "^15.2.1",
|
||||
@ -63,10 +65,8 @@
|
||||
"@types/jest": "^29.5.5",
|
||||
"@types/node": "^20.6.3",
|
||||
"concurrently": "^3.5.1",
|
||||
"esdoc": "^1.1.0",
|
||||
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
|
||||
"esdoc-standard-plugin": "^1.0.0",
|
||||
"eslint": "^8.49.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.17",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"prettier": "^3.0.3",
|
||||
@ -76,6 +76,8 @@
|
||||
"rollup-plugin-node-externals": "^6.1.1",
|
||||
"timers": "^0.1.1",
|
||||
"tsc-alias": "^1.8.8",
|
||||
"typedoc": "^0.25.1",
|
||||
"typedoc-plugin-markdown": "^3.16.0",
|
||||
"typescript": "^5.2.2",
|
||||
"uglify-js": "^3.17.4"
|
||||
},
|
||||
|
||||
31
scripts/generate-doc.ts
Normal file
31
scripts/generate-doc.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import * as path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
import {TSDocParser, TSDocConfiguration, ParserContext} from '@microsoft/tsdoc';
|
||||
import {TSDocConfigFile} from '@microsoft/tsdoc-config';
|
||||
|
||||
const mySourceFile = './src/shared/AbstractEvent/AbstractEvent.ts';
|
||||
|
||||
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(
|
||||
path.dirname(mySourceFile),
|
||||
);
|
||||
if (tsdocConfigFile.hasErrors) {
|
||||
// Report any errors
|
||||
console.log(tsdocConfigFile.getErrorSummary());
|
||||
}
|
||||
|
||||
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
|
||||
tsdocConfigFile.configureParser(tsdocConfiguration);
|
||||
const tsdocParser: TSDocParser = new TSDocParser(tsdocConfiguration);
|
||||
|
||||
// console.log(tsdocParser.configuration);
|
||||
|
||||
const parserContext: ParserContext = tsdocParser.parseString(
|
||||
fs.readFileSync(mySourceFile, {encoding: 'utf8'}),
|
||||
);
|
||||
|
||||
if (parserContext.log.messages.length > 0) {
|
||||
throw new Error(`Syntax error: ${parserContext.log.messages[0].text}`);
|
||||
}
|
||||
|
||||
console.log(parserContext.docComment.params.blocks);
|
||||
9
scripts/generate.ts
Normal file
9
scripts/generate.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import doc from '../src/shared/AbstractEvent/AbstractEvent.doc.json';
|
||||
|
||||
console.log(doc);
|
||||
|
||||
interface API {
|
||||
title: string;
|
||||
}
|
||||
|
||||
doc.children.forEach((child) => {});
|
||||
329
scripts/test.ts
Normal file
329
scripts/test.ts
Normal file
@ -0,0 +1,329 @@
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import colors from 'colors';
|
||||
import * as ts from 'typescript';
|
||||
import * as tsdoc from '@microsoft/tsdoc';
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
/**
|
||||
* Returns true if the specified SyntaxKind is part of a declaration form.
|
||||
*
|
||||
* Based on ts.isDeclarationKind() from the compiler.
|
||||
* https://github.com/microsoft/TypeScript/blob/v3.0.3/src/compiler/utilities.ts#L6382
|
||||
*/
|
||||
function isDeclarationKind(kind: ts.SyntaxKind): boolean {
|
||||
return (
|
||||
kind === ts.SyntaxKind.ArrowFunction ||
|
||||
kind === ts.SyntaxKind.BindingElement ||
|
||||
kind === ts.SyntaxKind.ClassDeclaration ||
|
||||
kind === ts.SyntaxKind.ClassExpression ||
|
||||
kind === ts.SyntaxKind.Constructor ||
|
||||
kind === ts.SyntaxKind.EnumDeclaration ||
|
||||
kind === ts.SyntaxKind.EnumMember ||
|
||||
kind === ts.SyntaxKind.ExportSpecifier ||
|
||||
kind === ts.SyntaxKind.FunctionDeclaration ||
|
||||
kind === ts.SyntaxKind.FunctionExpression ||
|
||||
kind === ts.SyntaxKind.GetAccessor ||
|
||||
kind === ts.SyntaxKind.ImportClause ||
|
||||
kind === ts.SyntaxKind.ImportEqualsDeclaration ||
|
||||
kind === ts.SyntaxKind.ImportSpecifier ||
|
||||
kind === ts.SyntaxKind.InterfaceDeclaration ||
|
||||
kind === ts.SyntaxKind.JsxAttribute ||
|
||||
kind === ts.SyntaxKind.MethodDeclaration ||
|
||||
kind === ts.SyntaxKind.MethodSignature ||
|
||||
kind === ts.SyntaxKind.ModuleDeclaration ||
|
||||
kind === ts.SyntaxKind.NamespaceExportDeclaration ||
|
||||
kind === ts.SyntaxKind.NamespaceImport ||
|
||||
kind === ts.SyntaxKind.Parameter ||
|
||||
kind === ts.SyntaxKind.PropertyAssignment ||
|
||||
kind === ts.SyntaxKind.PropertyDeclaration ||
|
||||
kind === ts.SyntaxKind.PropertySignature ||
|
||||
kind === ts.SyntaxKind.SetAccessor ||
|
||||
kind === ts.SyntaxKind.ShorthandPropertyAssignment ||
|
||||
kind === ts.SyntaxKind.TypeAliasDeclaration ||
|
||||
kind === ts.SyntaxKind.TypeParameter ||
|
||||
kind === ts.SyntaxKind.VariableDeclaration ||
|
||||
kind === ts.SyntaxKind.JSDocTypedefTag ||
|
||||
kind === ts.SyntaxKind.JSDocCallbackTag ||
|
||||
kind === ts.SyntaxKind.JSDocPropertyTag
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the JSDoc-style comments associated with a specific AST node.
|
||||
*
|
||||
* Based on ts.getJSDocCommentRanges() from the compiler.
|
||||
* https://github.com/microsoft/TypeScript/blob/v3.0.3/src/compiler/utilities.ts#L924
|
||||
*/
|
||||
function getJSDocCommentRanges(node: ts.Node, text: string): ts.CommentRange[] {
|
||||
const commentRanges: ts.CommentRange[] = [];
|
||||
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.Parameter:
|
||||
case ts.SyntaxKind.TypeParameter:
|
||||
case ts.SyntaxKind.FunctionExpression:
|
||||
case ts.SyntaxKind.ArrowFunction:
|
||||
case ts.SyntaxKind.ParenthesizedExpression:
|
||||
commentRanges.push(
|
||||
...(ts.getTrailingCommentRanges(text, node.pos) || []),
|
||||
);
|
||||
break;
|
||||
}
|
||||
commentRanges.push(...(ts.getLeadingCommentRanges(text, node.pos) || []));
|
||||
|
||||
// True if the comment starts with '/**' but not if it is '/**/'
|
||||
return commentRanges.filter(
|
||||
(comment) =>
|
||||
text.charCodeAt(comment.pos + 1) ===
|
||||
0x2a /* ts.CharacterCodes.asterisk */ &&
|
||||
text.charCodeAt(comment.pos + 2) ===
|
||||
0x2a /* ts.CharacterCodes.asterisk */ &&
|
||||
text.charCodeAt(comment.pos + 3) !== 0x2f /* ts.CharacterCodes.slash */,
|
||||
);
|
||||
}
|
||||
|
||||
interface FoundComment {
|
||||
compilerNode: ts.Node;
|
||||
textRange: tsdoc.TextRange;
|
||||
}
|
||||
|
||||
function walkCompilerAstAndFindComments(
|
||||
node: ts.Node,
|
||||
indent: string,
|
||||
foundComments: FoundComment[],
|
||||
): void {
|
||||
// The TypeScript AST doesn't store code comments directly. If you want to find *every* comment,
|
||||
// you would need to rescan the SourceFile tokens similar to how tsutils.forEachComment() works:
|
||||
// https://github.com/ajafff/tsutils/blob/v3.0.0/util/util.ts#L453
|
||||
//
|
||||
// However, for this demo we are modeling a tool that discovers declarations and then analyzes their doc comments,
|
||||
// so we only care about TSDoc that would conventionally be associated with an interesting AST node.
|
||||
|
||||
let foundCommentsSuffix = '';
|
||||
const buffer: string = node.getSourceFile().getFullText();
|
||||
|
||||
// Only consider nodes that are part of a declaration form. Without this, we could discover
|
||||
// the same comment twice (e.g. for a MethodDeclaration and its PublicKeyword).
|
||||
if (isDeclarationKind(node.kind)) {
|
||||
// Find "/** */" style comments associated with this node.
|
||||
// Note that this reinvokes the compiler's scanner -- the result is not cached.
|
||||
const comments: ts.CommentRange[] = getJSDocCommentRanges(node, buffer);
|
||||
|
||||
if (comments.length > 0) {
|
||||
if (comments.length === 1) {
|
||||
foundCommentsSuffix = colors.cyan(` (FOUND 1 COMMENT)`);
|
||||
} else {
|
||||
foundCommentsSuffix = colors.cyan(
|
||||
` (FOUND ${comments.length} COMMENTS)`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const comment of comments) {
|
||||
foundComments.push({
|
||||
compilerNode: node,
|
||||
textRange: tsdoc.TextRange.fromStringRange(
|
||||
buffer,
|
||||
comment.pos,
|
||||
comment.end,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`${indent}- ${ts.SyntaxKind[node.kind]}${foundCommentsSuffix}`);
|
||||
|
||||
return node.forEachChild((child) =>
|
||||
walkCompilerAstAndFindComments(child, `${indent} `, foundComments),
|
||||
);
|
||||
}
|
||||
|
||||
function dumpTSDocTree(docNode: tsdoc.DocNode, indent: string): void {
|
||||
let dumpText = '';
|
||||
if (docNode instanceof tsdoc.DocExcerpt) {
|
||||
const content: string = docNode.content.toString();
|
||||
dumpText +=
|
||||
colors.gray(`${indent}* ${docNode.excerptKind}=`) +
|
||||
colors.cyan(JSON.stringify(content));
|
||||
} else {
|
||||
dumpText += `${indent}- ${docNode.kind}`;
|
||||
}
|
||||
console.log(dumpText);
|
||||
|
||||
for (const child of docNode.getChildNodes()) {
|
||||
dumpTSDocTree(child, `${indent} `);
|
||||
}
|
||||
}
|
||||
|
||||
function parseTSDoc(foundComment: FoundComment): void {
|
||||
console.log(os.EOL + colors.green('Comment to be parsed:') + os.EOL);
|
||||
console.log(colors.gray('<<<<<<'));
|
||||
console.log(foundComment.textRange.toString());
|
||||
console.log(colors.gray('>>>>>>'));
|
||||
|
||||
const customConfiguration: tsdoc.TSDocConfiguration =
|
||||
new tsdoc.TSDocConfiguration();
|
||||
|
||||
// const customInlineDefinition: tsdoc.TSDocTagDefinition =
|
||||
// new tsdoc.TSDocTagDefinition({
|
||||
// tagName: '@class',
|
||||
// syntaxKind: tsdoc.TSDocTagSyntaxKind.InlineTag,
|
||||
// allowMultiple: true,
|
||||
// });
|
||||
|
||||
// NOTE: Defining this causes a new DocBlock to be created under docComment.customBlocks.
|
||||
// Otherwise, a simple DocBlockTag would appear inline in the @remarks section.
|
||||
const customBlockDefinition: tsdoc.TSDocTagDefinition =
|
||||
new tsdoc.TSDocTagDefinition({
|
||||
tagName: '@customBlock',
|
||||
syntaxKind: tsdoc.TSDocTagSyntaxKind.BlockTag,
|
||||
});
|
||||
|
||||
// NOTE: Defining this causes @customModifier to be removed from its section,
|
||||
// and added to the docComment.modifierTagSet
|
||||
const classModifierDefinition: tsdoc.TSDocTagDefinition =
|
||||
new tsdoc.TSDocTagDefinition({
|
||||
tagName: '@class',
|
||||
syntaxKind: tsdoc.TSDocTagSyntaxKind.ModifierTag,
|
||||
});
|
||||
|
||||
customConfiguration.addTagDefinitions([
|
||||
// customInlineDefinition,
|
||||
customBlockDefinition,
|
||||
classModifierDefinition,
|
||||
]);
|
||||
|
||||
console.log(
|
||||
`${os.EOL}Invoking TSDocParser with custom configuration...${os.EOL}`,
|
||||
);
|
||||
const tsdocParser: tsdoc.TSDocParser = new tsdoc.TSDocParser(
|
||||
customConfiguration,
|
||||
);
|
||||
const parserContext: tsdoc.ParserContext = tsdocParser.parseRange(
|
||||
foundComment.textRange,
|
||||
);
|
||||
const docComment: tsdoc.DocComment = parserContext.docComment;
|
||||
|
||||
console.log(os.EOL + colors.green('Parser Log Messages:') + os.EOL);
|
||||
|
||||
if (parserContext.log.messages.length === 0) {
|
||||
console.log('No errors or warnings.');
|
||||
} else {
|
||||
const sourceFile: ts.SourceFile = foundComment.compilerNode.getSourceFile();
|
||||
for (const message of parserContext.log.messages) {
|
||||
// Since we have the compiler's analysis, use it to calculate the line/column information,
|
||||
// since this is currently faster than TSDoc's TextRange.getLocation() lookup.
|
||||
const location: ts.LineAndCharacter =
|
||||
sourceFile.getLineAndCharacterOfPosition(message.textRange.pos);
|
||||
const formattedMessage = `${sourceFile.fileName}(${location.line + 1},${
|
||||
location.character + 1
|
||||
}): [TSDoc] ${message}`;
|
||||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (parserContext.docComment.modifierTagSet.hasTag(classModifierDefinition)) {
|
||||
console.log(
|
||||
os.EOL +
|
||||
colors.cyan(
|
||||
`The ${classModifierDefinition.tagName} modifier was FOUND.`,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
os.EOL +
|
||||
colors.cyan(
|
||||
`The ${classModifierDefinition.tagName} modifier was NOT FOUND.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
console.log(os.EOL + colors.green("Visiting TSDoc's DocNode tree") + os.EOL);
|
||||
dumpTSDocTree(docComment, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* The advanced demo invokes the TypeScript compiler and extracts the comment from the AST.
|
||||
* It also illustrates how to define custom TSDoc tags using TSDocConfiguration.
|
||||
*/
|
||||
export function advancedDemo(): void {
|
||||
console.log(
|
||||
colors.yellow('*** TSDoc API demo: Advanced Scenario ***') + os.EOL,
|
||||
);
|
||||
|
||||
const inputFilename: string = path.resolve(
|
||||
path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'src',
|
||||
'shared',
|
||||
'AbstractEvent',
|
||||
'AbstractEvent.ts',
|
||||
),
|
||||
);
|
||||
const compilerOptions: ts.CompilerOptions = {
|
||||
target: ts.ScriptTarget.ES5,
|
||||
};
|
||||
|
||||
// Compile the input
|
||||
console.log('Invoking the TypeScript compiler to analyze typescript files');
|
||||
|
||||
const program: ts.Program = ts.createProgram(
|
||||
[inputFilename],
|
||||
compilerOptions,
|
||||
);
|
||||
|
||||
// Report any compiler errors
|
||||
const compilerDiagnostics: ReadonlyArray<ts.Diagnostic> =
|
||||
program.getSemanticDiagnostics();
|
||||
if (compilerDiagnostics.length > 0) {
|
||||
for (const diagnostic of compilerDiagnostics) {
|
||||
const message: string = ts.flattenDiagnosticMessageText(
|
||||
diagnostic.messageText,
|
||||
os.EOL,
|
||||
);
|
||||
if (diagnostic.file) {
|
||||
const location: ts.LineAndCharacter =
|
||||
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
|
||||
const formattedMessage = `${diagnostic.file.fileName}(${
|
||||
location.line + 1
|
||||
},${location.character + 1}): [TypeScript] ${message}`;
|
||||
console.log(colors.red(formattedMessage));
|
||||
} else {
|
||||
console.log(colors.red(message));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('No compiler errors or warnings.');
|
||||
}
|
||||
|
||||
const sourceFile: ts.SourceFile | undefined =
|
||||
program.getSourceFile(inputFilename);
|
||||
if (!sourceFile) {
|
||||
throw new Error('Error retrieving source file');
|
||||
}
|
||||
|
||||
console.log(
|
||||
os.EOL +
|
||||
colors.green('Scanning compiler AST for first code comment...') +
|
||||
os.EOL,
|
||||
);
|
||||
|
||||
const foundComments: FoundComment[] = [];
|
||||
|
||||
walkCompilerAstAndFindComments(sourceFile, '', foundComments);
|
||||
|
||||
if (foundComments.length === 0) {
|
||||
console.log(
|
||||
colors.red('Error: No code comments were found in the input file'),
|
||||
);
|
||||
} else {
|
||||
foundComments.forEach(parseTSDoc);
|
||||
}
|
||||
}
|
||||
|
||||
advancedDemo();
|
||||
|
||||
/* eslint-enable no-console */
|
||||
12
scripts/tsconfig.json
Normal file
12
scripts/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "@shopify/typescript-configs/base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "../",
|
||||
"module": "commonjs",
|
||||
"target": "es2022",
|
||||
"esModuleInterop": true,
|
||||
"useUnknownInCatchVariables": false
|
||||
},
|
||||
"include": ["./**/*"]
|
||||
}
|
||||
@ -1,83 +1,128 @@
|
||||
export class EventNotCancelable extends Error {
|
||||
constructor(className: string) {
|
||||
super(`${className} cannot be canceled`);
|
||||
}
|
||||
}
|
||||
|
||||
export function testMe() {}
|
||||
|
||||
export interface Hmm {}
|
||||
|
||||
export enum Enum {}
|
||||
|
||||
export type AnotherTest = any;
|
||||
|
||||
export const test = {};
|
||||
|
||||
/**
|
||||
* All events fired by draggable inherit this class. You can call `cancel()` to
|
||||
* cancel a specific event or you can check if an event has been canceled by
|
||||
* calling `canceled()`.
|
||||
* @abstract
|
||||
* @class AbstractEvent
|
||||
* @module AbstractEvent
|
||||
*
|
||||
* @typeParam T - Describes the event data used in `this.data`
|
||||
*
|
||||
* @example **Creating a new custom event for Draggable**
|
||||
* ```ts
|
||||
* import {AbstractEvent} from '@shopify/draggable';
|
||||
*
|
||||
* interface CustomEventData {}
|
||||
*
|
||||
* class MyCustomEvent extends AbstractEvent<CustomEventData> {
|
||||
* static type = 'custom:event';
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @example **Triggering event via Draggable**
|
||||
* ```ts
|
||||
* import {Draggable, AbstractEvent} from '@shopify/draggable';
|
||||
*
|
||||
* interface CustomEventData {}
|
||||
*
|
||||
* class MyCustomEvent extends AbstractEvent<CustomEventData> {
|
||||
* static type = 'custom:event';
|
||||
* }
|
||||
*
|
||||
* const draggable = new Draggable({draggable: 'li'});
|
||||
*
|
||||
* draggable.on('custom:event', (event) => {
|
||||
* console.log(event);
|
||||
* })
|
||||
*
|
||||
* draggable.trigger(new MyCustomEvent({}));
|
||||
* ```
|
||||
*/
|
||||
export class AbstractEvent<T> {
|
||||
/**
|
||||
* Event type
|
||||
* @static
|
||||
* @abstract
|
||||
* @property type
|
||||
* @type {String}
|
||||
* Event type name which is used for triggering and listening to events
|
||||
* Override this so you can
|
||||
* @virtual
|
||||
*/
|
||||
static type = 'event';
|
||||
/**
|
||||
* Event cancelable
|
||||
* @static
|
||||
* @abstract
|
||||
* @property cancelable
|
||||
* @type {Boolean}
|
||||
* @virtual
|
||||
*/
|
||||
static cancelable = false;
|
||||
|
||||
/**
|
||||
* Private instance variable to track canceled state
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
* @internal
|
||||
*/
|
||||
private _canceled = false;
|
||||
#canceled = false;
|
||||
|
||||
/**
|
||||
* AbstractEvent constructor.
|
||||
* @constructs AbstractEvent
|
||||
* @param {T} data - Event data
|
||||
* Creates an `AbstractEvent` instance.
|
||||
* @public
|
||||
* @sealed
|
||||
* @param data - Event data for this even instance
|
||||
* @typeParam T - Describes the event data used in `this.data`
|
||||
*/
|
||||
constructor(public data: T) {}
|
||||
|
||||
/**
|
||||
* Read-only type
|
||||
* @abstract
|
||||
* @return {String}
|
||||
* Read-only property to find out event type
|
||||
* @readonly
|
||||
* @sealed
|
||||
*/
|
||||
get type() {
|
||||
return (this.constructor as typeof AbstractEvent).type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-only cancelable
|
||||
* @abstract
|
||||
* @return {Boolean}
|
||||
* Read-only property to check if event is cancelable
|
||||
* @readonly
|
||||
* @sealed
|
||||
*/
|
||||
get cancelable() {
|
||||
return (this.constructor as typeof AbstractEvent).cancelable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the event instance
|
||||
* @abstract
|
||||
* Marks the event instance as canceled
|
||||
* @throws {@link EventNotCancelable}
|
||||
* This exception is thrown if the event is not cancelable
|
||||
*/
|
||||
cancel() {
|
||||
this._canceled = true;
|
||||
if (!this.cancelable) {
|
||||
throw new EventNotCancelable(this.constructor.name);
|
||||
}
|
||||
|
||||
this.#canceled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event has been canceled
|
||||
* @abstract
|
||||
* @return {Boolean}
|
||||
* Checks if event has been canceled
|
||||
* @returns True if `cancel()` has been called
|
||||
*/
|
||||
canceled() {
|
||||
return this._canceled;
|
||||
return this.#canceled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new event instance with existing event data.
|
||||
* This method allows for overriding of event data.
|
||||
* @param {T} data
|
||||
* @return {AbstractEvent}
|
||||
* @param T -
|
||||
* @returns A new event instance
|
||||
*/
|
||||
clone(data: T) {
|
||||
return new (this.constructor as typeof AbstractEvent)({
|
||||
@ -86,3 +131,9 @@ export class AbstractEvent<T> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const event = new AbstractEvent<{[key: string]: any}>({});
|
||||
|
||||
event.clone({
|
||||
tst: 'a',
|
||||
});
|
||||
|
||||
10
tsdoc.json
Normal file
10
tsdoc.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
||||
"extends": ["typedoc/tsdoc.json"],
|
||||
"tagDefinitions": [
|
||||
{
|
||||
"tagName": "@cancelable",
|
||||
"syntaxKind": "modifier"
|
||||
}
|
||||
]
|
||||
}
|
||||
10
typedoc.json
Normal file
10
typedoc.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"entryPoints": ["./src/**/*.ts"],
|
||||
"out": "./docs",
|
||||
"exclude": ["./src/**/index.ts", "./src/**/*.test.ts"],
|
||||
"includeVersion": true,
|
||||
"githubPages": false,
|
||||
"gitRevision": "main",
|
||||
"plugin": ["typedoc-plugin-markdown"]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user