Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { _Parser } from './Parser.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
import type { Token, TokensList } from './Tokens.ts';

export class _Hooks {
options: MarkedOptions;
export class _Hooks<ParserOutput = string, RendererOutput = string> {
options: MarkedOptions<ParserOutput, RendererOutput>;
block?: boolean;

constructor(options?: MarkedOptions) {
constructor(options?: MarkedOptions<ParserOutput, RendererOutput>) {
this.options = options || _defaults;
}

Expand All @@ -28,7 +28,7 @@ export class _Hooks {
/**
* Process HTML after marked is finished
*/
postprocess(html: string) {
postprocess(html: ParserOutput) {
return html;
}

Expand All @@ -50,6 +50,6 @@ export class _Hooks {
* Provide function to parse tokens
*/
provideParser() {
return this.block ? _Parser.parse : _Parser.parseInline;
return this.block ? _Parser.parse<ParserOutput, RendererOutput> : _Parser.parseInline<ParserOutput, RendererOutput>;
}
}
54 changes: 27 additions & 27 deletions src/Instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ export type MaybePromise = void | Promise<void>;
type UnknownFunction = (...args: unknown[]) => unknown;
type GenericRendererFunction = (...args: unknown[]) => string | false;

export class Marked {
defaults = _getDefaults();
export class Marked<ParserOutput = string, RendererOutput = string> {
defaults = _getDefaults<ParserOutput, RendererOutput>();
options = this.setOptions;

parse = this.parseMarkdown(true);
parseInline = this.parseMarkdown(false);

Parser = _Parser;
Renderer = _Renderer;
TextRenderer = _TextRenderer;
Parser = _Parser<ParserOutput, RendererOutput>;
Renderer = _Renderer<ParserOutput, RendererOutput>;
TextRenderer = _TextRenderer<RendererOutput>;
Lexer = _Lexer;
Tokenizer = _Tokenizer;
Hooks = _Hooks;
Tokenizer = _Tokenizer<ParserOutput, RendererOutput>;
Hooks = _Hooks<ParserOutput, RendererOutput>;

constructor(...args: MarkedExtension[]) {
constructor(...args: MarkedExtension<ParserOutput, RendererOutput>[]) {
this.use(...args);
}

Expand Down Expand Up @@ -73,12 +73,12 @@ export class Marked {
return values;
}

use(...args: MarkedExtension[]) {
const extensions: MarkedOptions['extensions'] = this.defaults.extensions || { renderers: {}, childTokens: {} };
use(...args: MarkedExtension<ParserOutput, RendererOutput>[]) {
const extensions: MarkedOptions<ParserOutput, RendererOutput>['extensions'] = this.defaults.extensions || { renderers: {}, childTokens: {} };

args.forEach((pack) => {
// copy options to new object
const opts = { ...pack } as MarkedOptions;
const opts = { ...pack } as MarkedOptions<ParserOutput, RendererOutput>;

// set async to true if it was set to true before
opts.async = this.defaults.async || opts.async || false;
Expand Down Expand Up @@ -139,7 +139,7 @@ export class Marked {

// ==-- Parse "overwrite" extensions --== //
if (pack.renderer) {
const renderer = this.defaults.renderer || new _Renderer(this.defaults);
const renderer = this.defaults.renderer || new _Renderer<ParserOutput, RendererOutput>(this.defaults);
for (const prop in pack.renderer) {
if (!(prop in renderer)) {
throw new Error(`renderer '${prop}' does not exist`);
Expand All @@ -148,7 +148,7 @@ export class Marked {
// ignore options property
continue;
}
const rendererProp = prop as Exclude<keyof _Renderer, 'options' | 'parser'>;
const rendererProp = prop as Exclude<keyof _Renderer<ParserOutput, RendererOutput>, 'options' | 'parser'>;
const rendererFunc = pack.renderer[rendererProp] as GenericRendererFunction;
const prevRenderer = renderer[rendererProp] as GenericRendererFunction;
// Replace renderer with func to run extension, but fall back if false
Expand All @@ -157,13 +157,13 @@ export class Marked {
if (ret === false) {
ret = prevRenderer.apply(renderer, args);
}
return ret || '';
return (ret || '') as RendererOutput;
};
}
opts.renderer = renderer;
}
if (pack.tokenizer) {
const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
const tokenizer = this.defaults.tokenizer || new _Tokenizer<ParserOutput, RendererOutput>(this.defaults);
for (const prop in pack.tokenizer) {
if (!(prop in tokenizer)) {
throw new Error(`tokenizer '${prop}' does not exist`);
Expand All @@ -172,7 +172,7 @@ export class Marked {
// ignore options, rules, and lexer properties
continue;
}
const tokenizerProp = prop as Exclude<keyof _Tokenizer, 'options' | 'rules' | 'lexer'>;
const tokenizerProp = prop as Exclude<keyof _Tokenizer<ParserOutput, RendererOutput>, 'options' | 'rules' | 'lexer'>;
const tokenizerFunc = pack.tokenizer[tokenizerProp] as UnknownFunction;
const prevTokenizer = tokenizer[tokenizerProp] as UnknownFunction;
// Replace tokenizer with func to run extension, but fall back if false
Expand All @@ -190,7 +190,7 @@ export class Marked {

// ==-- Parse Hooks extensions --== //
if (pack.hooks) {
const hooks = this.defaults.hooks || new _Hooks();
const hooks = this.defaults.hooks || new _Hooks<ParserOutput, RendererOutput>();
for (const prop in pack.hooks) {
if (!(prop in hooks)) {
throw new Error(`hook '${prop}' does not exist`);
Expand All @@ -199,7 +199,7 @@ export class Marked {
// ignore options and block properties
continue;
}
const hooksProp = prop as Exclude<keyof _Hooks, 'options' | 'block'>;
const hooksProp = prop as Exclude<keyof _Hooks<ParserOutput, RendererOutput>, 'options' | 'block'>;
const hooksFunc = pack.hooks[hooksProp] as UnknownFunction;
const prevHook = hooks[hooksProp] as UnknownFunction;
if (_Hooks.passThroughHooks.has(prop)) {
Expand Down Expand Up @@ -248,28 +248,28 @@ export class Marked {
return this;
}

setOptions(opt: MarkedOptions) {
setOptions(opt: MarkedOptions<ParserOutput, RendererOutput>) {
this.defaults = { ...this.defaults, ...opt };
return this;
}

lexer(src: string, options?: MarkedOptions) {
lexer(src: string, options?: MarkedOptions<ParserOutput, RendererOutput>) {
return _Lexer.lex(src, options ?? this.defaults);
}

parser(tokens: Token[], options?: MarkedOptions) {
return _Parser.parse(tokens, options ?? this.defaults);
parser(tokens: Token[], options?: MarkedOptions<ParserOutput, RendererOutput>) {
return _Parser.parse<ParserOutput, RendererOutput>(tokens, options ?? this.defaults);
}

private parseMarkdown(blockType: boolean) {
type overloadedParse = {
(src: string, options: MarkedOptions & { async: true }): Promise<string>;
(src: string, options: MarkedOptions & { async: false }): string;
(src: string, options?: MarkedOptions | null): string | Promise<string>;
(src: string, options: MarkedOptions<ParserOutput, RendererOutput> & { async: true }): Promise<ParserOutput>;
(src: string, options: MarkedOptions<ParserOutput, RendererOutput> & { async: false }): ParserOutput;
(src: string, options?: MarkedOptions<ParserOutput, RendererOutput> | null): ParserOutput | Promise<ParserOutput>;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parse: overloadedParse = (src: string, options?: MarkedOptions | null): any => {
const parse: overloadedParse = (src: string, options?: MarkedOptions<ParserOutput, RendererOutput> | null): any => {
const origOpt = { ...options };
const opt = { ...this.defaults, ...origOpt };

Expand Down Expand Up @@ -320,7 +320,7 @@ export class Marked {
}
let html = parser(tokens, opt);
if (opt.hooks) {
html = opt.hooks.postprocess(html) as string;
html = opt.hooks.postprocess(html);
}
return html;
} catch(e) {
Expand Down
18 changes: 9 additions & 9 deletions src/Lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ import type { MarkedOptions } from './MarkedOptions.ts';
/**
* Block Lexer
*/
export class _Lexer {
export class _Lexer<ParserOutput = string, RendererOutput = string> {
tokens: TokensList;
options: MarkedOptions;
options: MarkedOptions<ParserOutput, RendererOutput>;
state: {
inLink: boolean;
inRawBlock: boolean;
top: boolean;
};

private tokenizer: _Tokenizer;
private tokenizer: _Tokenizer<ParserOutput, RendererOutput>;
private inlineQueue: { src: string, tokens: Token[] }[];

constructor(options?: MarkedOptions) {
constructor(options?: MarkedOptions<ParserOutput, RendererOutput>) {
// TokenList cannot be created in one go
this.tokens = [] as unknown as TokensList;
this.tokens.links = Object.create(null);
this.options = options || _defaults;
this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
this.options.tokenizer = this.options.tokenizer || new _Tokenizer<ParserOutput, RendererOutput>();
this.tokenizer = this.options.tokenizer;
this.tokenizer.options = this.options;
this.tokenizer.lexer = this;
Expand Down Expand Up @@ -68,16 +68,16 @@ export class _Lexer {
/**
* Static Lex Method
*/
static lex(src: string, options?: MarkedOptions) {
const lexer = new _Lexer(options);
static lex<ParserOutput = string, RendererOutput = string>(src: string, options?: MarkedOptions<ParserOutput, RendererOutput>) {
const lexer = new _Lexer<ParserOutput, RendererOutput>(options);
return lexer.lex(src);
}

/**
* Static Lex Inline Method
*/
static lexInline(src: string, options?: MarkedOptions) {
const lexer = new _Lexer(options);
static lexInline<ParserOutput = string, RendererOutput = string>(src: string, options?: MarkedOptions<ParserOutput, RendererOutput>) {
const lexer = new _Lexer<ParserOutput, RendererOutput>(options);
return lexer.inlineTokens(src);
}

Expand Down
48 changes: 24 additions & 24 deletions src/MarkedOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,35 @@ export interface TokenizerExtension {
childTokens?: string[];
}

export interface RendererThis {
parser: _Parser;
export interface RendererThis<ParserOutput = string, RendererOutput = string> {
parser: _Parser<ParserOutput, RendererOutput>;
}

export type RendererExtensionFunction = (this: RendererThis, token: Tokens.Generic) => string | false | undefined;
export type RendererExtensionFunction<ParserOutput = string, RendererOutput = string> = (this: RendererThis<ParserOutput, RendererOutput>, token: Tokens.Generic) => RendererOutput | false | undefined;

export interface RendererExtension {
export interface RendererExtension<ParserOutput = string, RendererOutput = string> {
name: string;
renderer: RendererExtensionFunction;
renderer: RendererExtensionFunction<ParserOutput, RendererOutput>;
}

export type TokenizerAndRendererExtension = TokenizerExtension | RendererExtension | (TokenizerExtension & RendererExtension);
export type TokenizerAndRendererExtension<ParserOutput = string, RendererOutput = string> = TokenizerExtension | RendererExtension<ParserOutput, RendererOutput> | (TokenizerExtension & RendererExtension<ParserOutput, RendererOutput>);

type HooksApi = Omit<_Hooks, 'constructor' | 'options' | 'block'>;
type HooksObject = {
[K in keyof HooksApi]?: (this: _Hooks, ...args: Parameters<HooksApi[K]>) => ReturnType<HooksApi[K]> | Promise<ReturnType<HooksApi[K]>>
type HooksApi<ParserOutput = string, RendererOutput = string> = Omit<_Hooks<ParserOutput, RendererOutput>, 'constructor' | 'options' | 'block'>;
type HooksObject<ParserOutput = string, RendererOutput = string> = {
[K in keyof HooksApi<ParserOutput, RendererOutput>]?: (this: _Hooks<ParserOutput, RendererOutput>, ...args: Parameters<HooksApi<ParserOutput, RendererOutput>[K]>) => ReturnType<HooksApi<ParserOutput, RendererOutput>[K]> | Promise<ReturnType<HooksApi<ParserOutput, RendererOutput>[K]>>
};

type RendererApi = Omit<_Renderer, 'constructor' | 'options' | 'parser'>;
type RendererObject = {
[K in keyof RendererApi]?: (this: _Renderer, ...args: Parameters<RendererApi[K]>) => ReturnType<RendererApi[K]> | false
type RendererApi<ParserOutput = string, RendererOutput = string> = Omit<_Renderer<ParserOutput, RendererOutput>, 'constructor' | 'options' | 'parser'>;
type RendererObject<ParserOutput = string, RendererOutput = string> = {
[K in keyof RendererApi<ParserOutput, RendererOutput>]?: (this: _Renderer<ParserOutput, RendererOutput>, ...args: Parameters<RendererApi<ParserOutput, RendererOutput>[K]>) => ReturnType<RendererApi<ParserOutput, RendererOutput>[K]> | false
};

type TokenizerApi = Omit<_Tokenizer, 'constructor' | 'options' | 'rules' | 'lexer'>;
type TokenizerObject = {
[K in keyof TokenizerApi]?: (this: _Tokenizer, ...args: Parameters<TokenizerApi[K]>) => ReturnType<TokenizerApi[K]> | false
type TokenizerApi<ParserOutput = string, RendererOutput = string> = Omit<_Tokenizer<ParserOutput, RendererOutput>, 'constructor' | 'options' | 'rules' | 'lexer'>;
type TokenizerObject<ParserOutput = string, RendererOutput = string> = {
[K in keyof TokenizerApi<ParserOutput, RendererOutput>]?: (this: _Tokenizer<ParserOutput, RendererOutput>, ...args: Parameters<TokenizerApi<ParserOutput, RendererOutput>[K]>) => ReturnType<TokenizerApi<ParserOutput, RendererOutput>[K]> | false
};

export interface MarkedExtension {
export interface MarkedExtension<ParserOutput = string, RendererOutput = string> {
/**
* True will tell marked to await any walkTokens functions before parsing the tokens and returning an HTML string.
*/
Expand All @@ -64,7 +64,7 @@ export interface MarkedExtension {
* Add tokenizers and renderers to marked
*/
extensions?:
| TokenizerAndRendererExtension[]
| TokenizerAndRendererExtension<ParserOutput, RendererOutput>[]
| null;

/**
Expand All @@ -80,7 +80,7 @@ export interface MarkedExtension {
* provideLexer is called to provide a function to tokenize markdown.
* provideParser is called to provide a function to parse tokens.
*/
hooks?: HooksObject | null;
hooks?: HooksObject<ParserOutput, RendererOutput> | null;

/**
* Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
Expand All @@ -92,7 +92,7 @@ export interface MarkedExtension {
*
* An object containing functions to render tokens to HTML.
*/
renderer?: RendererObject | null;
renderer?: RendererObject<ParserOutput, RendererOutput> | null;

/**
* Shows an HTML error message when rendering fails.
Expand All @@ -113,30 +113,30 @@ export interface MarkedExtension {
walkTokens?: ((token: Token) => void | Promise<void>) | null;
}

export interface MarkedOptions extends Omit<MarkedExtension, 'hooks' | 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
export interface MarkedOptions<ParserOutput = string, RendererOutput = string> extends Omit<MarkedExtension<ParserOutput, RendererOutput>, 'hooks' | 'renderer' | 'tokenizer' | 'extensions' | 'walkTokens'> {
/**
* Hooks are methods that hook into some part of marked.
*/
hooks?: _Hooks | null;
hooks?: _Hooks<ParserOutput, RendererOutput> | null;

/**
* Type: object Default: new Renderer()
*
* An object containing functions to render tokens to HTML.
*/
renderer?: _Renderer | null;
renderer?: _Renderer<ParserOutput, RendererOutput> | null;

/**
* The tokenizer defines how to turn markdown text into tokens.
*/
tokenizer?: _Tokenizer | null;
tokenizer?: _Tokenizer<ParserOutput, RendererOutput> | null;

/**
* Custom extensions
*/
extensions?: null | {
renderers: {
[name: string]: RendererExtensionFunction;
[name: string]: RendererExtensionFunction<ParserOutput, RendererOutput>;
};
childTokens: {
[name: string]: string[];
Expand Down
Loading