diff --git a/types/commonmark/commonmark-tests.ts b/types/commonmark/commonmark-tests.ts index d298972f89..8d3a3a5447 100644 --- a/types/commonmark/commonmark-tests.ts +++ b/types/commonmark/commonmark-tests.ts @@ -1,9 +1,6 @@ - - import commonmark = require('commonmark'); function logNode(node: commonmark.Node) { - console.log( node.destination, node.firstChild, @@ -24,12 +21,10 @@ function logNode(node: commonmark.Node) { node.sourcepos, node.title, node.type); - } -var parser = new commonmark.Parser({ smart: true, time: true }); -var node = parser.parse('# a piece of _markdown_'); - +const parser = new commonmark.Parser({ smart: true, time: true }); +const node = parser.parse('# a piece of _markdown_'); let w = node.walker(); let step = w.next(); @@ -37,11 +32,75 @@ if (step.entering) { logNode(step.node); } - let xmlRenderer = new commonmark.XmlRenderer({ sourcepos: true, time: true }); let xml = xmlRenderer.render(node); console.log(xml); -let htmlRenderer = new commonmark.HtmlRenderer({ safe: true, smart: true, sourcepos: true, time: true}); +let htmlRenderer = new commonmark.HtmlRenderer({ safe: true, smart: true, sourcepos: true, time: true }); let html = htmlRenderer.render(node); -console.log(html); \ No newline at end of file +console.log(html); + +function basic_usage() { + const reader = new commonmark.Parser(); + const writer = new commonmark.HtmlRenderer(); + const parsed = reader.parse('Hello *world*'); // parsed is a 'Node' tree + // transform parsed if you like... + const result = writer.render(parsed); // result is a String +} + +function constructor_optional_options() { + const writer = new commonmark.HtmlRenderer({ sourcepos: true }); +} + +function soft_breaks_as_hard_breaks() { + const writer = new commonmark.HtmlRenderer(); + writer.softbreak = '
'; +} + +function soft_breaks_as_spaces() { + const writer = new commonmark.HtmlRenderer(); + writer.softbreak = ' '; +} + +function text_to_ALL_CAPS(parsed: commonmark.Node) { + const walker = parsed.walker(); + let event: commonmark.NodeWalkingStep; + let node: commonmark.Node; + + event = walker.next(); + while (event) { + node = event.node; + if (event.entering && node.type === 'text') { + node.literal = node.literal!.toUpperCase(); + } + event = walker.next(); + } +} + +function emphasis_to_ALL_CAPS(parsed: commonmark.Node) { + const walker = parsed.walker(); + let event: commonmark.NodeWalkingStep; + let node: commonmark.Node; + let inEmph = false; + + event = walker.next(); + while (event) { + node = event.node; + if (node.type === 'emph') { + if (event.entering) { + inEmph = true; + } else { + inEmph = false; + // add Emph node's children as siblings + while (node.firstChild) { + node.insertBefore(node.firstChild); + } + // remove the empty Emph node + node.unlink(); + } + } else if (inEmph && node.type === 'text') { + node.literal = node.literal!.toUpperCase(); + } + event = walker.next(); + } +} diff --git a/types/commonmark/index.d.ts b/types/commonmark/index.d.ts index bba8cd7e36..d9ce80b1a5 100644 --- a/types/commonmark/index.d.ts +++ b/types/commonmark/index.d.ts @@ -1,212 +1,221 @@ -// Type definitions for commonmark.js 0.22.1 +// Type definitions for commonmark.js 0.27 // Project: https://github.com/jgm/commonmark.js // Definitions by: Nico Jansen +// Leonard Thieu // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -export = commonmark; -export as namespace commonmark; - -declare namespace commonmark { - - export interface NodeWalkingStep { - /** - * a boolean, which is true when we enter a Node from a parent or sibling, and false when we reenter it from a child - */ - entering: boolean; - /** - * The node belonging to this step - */ - node: Node; - } - - export interface NodeWalker { - /** - * Returns an object with properties entering and node. Returns null when we have finished walking the tree. - */ - next(): NodeWalkingStep; - /** - * Resets the iterator to resume at the specified node and setting for entering. (Normally this isn't needed unless you do destructive updates to the Node tree.) - */ - resumeAt(node: Node, entering?: boolean): void; - } - - export interface Position extends Array> { - } - - export interface ListData { - type?: string, - tight?: boolean, - delimiter?: string, - bulletChar?: string - } - - export class Node { - constructor(nodeType: string, sourcepos?: Position); - isContainer: boolean; - - /** - * (read-only): one of Text, Softbreak, Hardbreak, Emph, Strong, Html, Link, Image, Code, Document, Paragraph, BlockQuote, Item, List, Heading, CodeBlock, HtmlBlock ThematicBreak. - */ - type: string; - /** - * (read-only): a Node or null. - */ - firstChild: Node; - /** - * (read-only): a Node or null. - */ - lastChild: Node; - /** - * (read-only): a Node or null. - */ - next: Node; - /** - * (read-only): a Node or null. - */ - prev: Node; - /** - * (read-only): a Node or null. - */ - parent: Node; - /** - * (read-only): an Array with the following form: [[startline, startcolumn], [endline, endcolumn]] - */ - sourcepos: Position; - /** - * the literal String content of the node or null. - */ - literal: string; - /** - * link or image destination (String) or null. - */ - destination: string; - /** - * link or image title (String) or null. - */ - title: string; - /** - * fenced code block info string (String) or null. - */ - info: string; - /** - * heading level (Number). - */ - level: number; - /** - * either Bullet or Ordered (or undefined). - */ - listType: string; - /** - * true if list is tight - */ - listTight: boolean; - /** - * a Number, the starting number of an ordered list. - */ - listStart: number; - /** - * a String, either ) or . for an ordered list. - */ - listDelimiter: string; - /** - * used only for CustomBlock or CustomInline. - */ - onEnter: string; - /** - * used only for CustomBlock or CustomInline. - */ - onExit: string; - /** - * Append a Node child to the end of the Node's children. - */ - appendChild(child: Node): void; - /** - * Prepend a Node child to the beginning of the Node's children. - */ - prependChild(child: Node): void; - /** - * Remove the Node from the tree, severing its links with siblings and parents, and closing up gaps as needed. - */ - unlink(): void; - /** - * Insert a Node sibling after the Node. - */ - insertAfter(sibling: Node): void; - /** - * Insert a Node sibling before the Node. - */ - insertBefore(sibling: Node): void; - /** - * Returns a NodeWalker that can be used to iterate through the Node tree rooted in the Node - */ - walker(): NodeWalker; - /** - * Setting the backing object of listType, listTight, listStat and listDelimiter directly. - * Not needed unless creating list nodes directly. Should be fixed from v>0.22.1 - * https://github.com/jgm/commonmark.js/issues/74 - */ - _listData: ListData; - } +export class Node { + constructor(nodeType: string, sourcepos?: Position); /** - * Instead of converting Markdown directly to HTML, as most converters do, commonmark.js parses Markdown to an AST (abstract syntax tree), and then renders this AST as HTML. - * This opens up the possibility of manipulating the AST between parsing and rendering. For example, one could transform emphasis into ALL CAPS. + * (read-only): a String, one of text, softbreak, linebreak, emph, strong, html_inline, link, image, code, document, paragraph, + * block_quote, item, list, heading, code_block, html_block, thematic_break. */ - export class Parser { - /** - * Constructs a new Parser - */ - constructor(options?: ParserOptions); - parse(input: string): Node; - } + readonly type: 'text' | 'softbreak' | 'linebreak' | 'emph' | 'strong' | 'html_inline' | 'link' | 'image' | 'code' | 'document' | + 'paragraph' | 'block_quote' | 'item' | 'list' | 'heading' | 'code_block' | 'html_block' | 'thematic_break'; + /** + * (read-only): a Node or null. + */ + readonly firstChild: Node | null; + /** + * (read-only): a Node or null. + */ + readonly lastChild: Node | null; + /** + * (read-only): a Node or null. + */ + readonly next: Node | null; + /** + * (read-only): a Node or null. + */ + readonly prev: Node | null; + /** + * (read-only): a Node or null. + */ + readonly parent: Node | null; + /** + * (read-only): an Array with the following form: [[startline, startcolumn], [endline, endcolumn]] + */ + readonly sourcepos: Position; + /** + * (read-only): true if the Node can contain other Nodes as children. + */ + readonly isContainer: boolean; + /** + * the literal String content of the node or null. + */ + literal: string | null; + /** + * link or image destination (String) or null. + */ + destination: string | null; + /** + * link or image title (String) or null. + */ + title: string | null; + /** + * fenced code block info string (String) or null. + */ + info: string | null; + /** + * heading level (Number). + */ + level: number; + /** + * either Bullet or Ordered (or undefined). + */ + listType: 'Bullet' | 'Ordered'; + /** + * true if list is tight + */ + listTight: boolean; + /** + * a Number, the starting number of an ordered list. + */ + listStart: number; + /** + * a String, either ) or . for an ordered list. + */ + listDelimiter: ')' | '.'; + /** + * used only for CustomBlock or CustomInline. + */ + onEnter: string; + /** + * used only for CustomBlock or CustomInline. + */ + onExit: string; - export interface ParserOptions { - /** - * if true, straight quotes will be made curly, -- will be changed to an en dash, --- will be changed to an em dash, and ... will be changed to ellipses. - */ - smart?: boolean; - time?: boolean; - } + /** + * Append a Node child to the end of the Node's children. + */ + appendChild(child: Node): void; - export interface HtmlRenderingOptions extends XmlRenderingOptions { - /** - * if true, raw HTML will not be passed through to HTML output (it will be replaced by comments), and potentially unsafe URLs in links and images (those beginning with javascript:, vbscript:, file:, and with a few exceptions data:) will be replaced with empty strings. - */ - safe?: boolean; - /** - * if true, straight quotes will be made curly, -- will be changed to an en dash, --- will be changed to an em dash, and ... will be changed to ellipses. - */ - smart?: boolean; - /** - * if true, source position information for block-level elements will be rendered in the data-sourcepos attribute (for HTML) or the sourcepos attribute (for XML). - */ - sourcepos?: boolean; - } + /** + * Prepend a Node child to the beginning of the Node's children. + */ + prependChild(child: Node): void; - export class HtmlRenderer { - constructor(options?: HtmlRenderingOptions) - render(root: Node): string; - /** - * Let's you override the softbreak properties of a renderer. So, to make soft breaks render as hard breaks in HTML: - * writer.softbreak = "
"; - */ - softbreak: string; - /** - * Override the function that will be used to escape (sanitize) the html output. Return value is used to add to the html output - * @param input the input to escape - * @param isAttributeValue indicates wheter or not the input value will be used as value of an html attribute. - */ - escape: (input: string, isAttributeValue: boolean) => string; - } + /** + * Remove the Node from the tree, severing its links with siblings and parents, and closing up gaps as needed. + */ + unlink(): void; - export interface XmlRenderingOptions { - time?: boolean; - sourcepos?: boolean; - } + /** + * Insert a Node sibling after the Node. + */ + insertAfter(sibling: Node): void; - export class XmlRenderer { - constructor(options?: XmlRenderingOptions) - render(root: Node): string; - } + /** + * Insert a Node sibling before the Node. + */ + insertBefore(sibling: Node): void; + /** + * Returns a NodeWalker that can be used to iterate through the Node tree rooted in the Node + */ + walker(): NodeWalker; + + /** + * Setting the backing object of listType, listTight, listStat and listDelimiter directly. + * Not needed unless creating list nodes directly. Should be fixed from v>0.22.1 + * https://github.com/jgm/commonmark.js/issues/74 + */ + _listData: ListData; +} + +/** + * Instead of converting Markdown directly to HTML, as most converters do, commonmark.js parses Markdown to an AST (abstract syntax tree), and then renders this AST as HTML. + * This opens up the possibility of manipulating the AST between parsing and rendering. For example, one could transform emphasis into ALL CAPS. + */ +export class Parser { + /** + * Constructs a new Parser + */ + constructor(options?: ParserOptions); + + parse(input: string): Node; +} + +export class HtmlRenderer { + constructor(options?: HtmlRenderingOptions) + + render(root: Node): string; + + /** + * Let's you override the softbreak properties of a renderer. So, to make soft breaks render as hard breaks in HTML: + * writer.softbreak = "
"; + */ + softbreak: string; + /** + * Override the function that will be used to escape (sanitize) the html output. Return value is used to add to the html output + * @param input the input to escape + * @param isAttributeValue indicates wheter or not the input value will be used as value of an html attribute. + */ + escape: (input: string, isAttributeValue: boolean) => string; +} + +export class XmlRenderer { + constructor(options?: XmlRenderingOptions) + + render(root: Node): string; +} +export interface NodeWalkingStep { + /** + * a boolean, which is true when we enter a Node from a parent or sibling, and false when we reenter it from a child + */ + entering: boolean; + /** + * The node belonging to this step + */ + node: Node; +} + +export interface NodeWalker { + /** + * Returns an object with properties entering and node. Returns null when we have finished walking the tree. + */ + next(): NodeWalkingStep; + /** + * Resets the iterator to resume at the specified node and setting for entering. (Normally this isn't needed unless you do destructive updates to the Node tree.) + */ + resumeAt(node: Node, entering?: boolean): void; +} + +export type Position = [[number, number], [number, number]]; + +export interface ListData { + type?: string; + tight?: boolean; + delimiter?: string; + bulletChar?: string; +} + +export interface ParserOptions { + /** + * if true, straight quotes will be made curly, -- will be changed to an en dash, --- will be changed to an em dash, and ... will be changed to ellipses. + */ + smart?: boolean; + time?: boolean; +} + +export interface HtmlRenderingOptions extends XmlRenderingOptions { + /** + * if true, raw HTML will not be passed through to HTML output (it will be replaced by comments), and potentially unsafe URLs in links and images + * (those beginning with javascript:, vbscript:, file:, and with a few exceptions data:) will be replaced with empty strings. + */ + safe?: boolean; + /** + * if true, straight quotes will be made curly, -- will be changed to an en dash, --- will be changed to an em dash, and ... will be changed to ellipses. + */ + smart?: boolean; + /** + * if true, source position information for block-level elements will be rendered in the data-sourcepos attribute (for HTML) or the sourcepos attribute (for XML). + */ + sourcepos?: boolean; +} + +export interface XmlRenderingOptions { + time?: boolean; + sourcepos?: boolean; } diff --git a/types/commonmark/tsconfig.json b/types/commonmark/tsconfig.json index e424e972ca..82e3004b78 100644 --- a/types/commonmark/tsconfig.json +++ b/types/commonmark/tsconfig.json @@ -7,7 +7,7 @@ ], "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -20,4 +20,4 @@ "index.d.ts", "commonmark-tests.ts" ] -} \ No newline at end of file +} diff --git a/types/commonmark/tslint.json b/types/commonmark/tslint.json new file mode 100644 index 0000000000..f93cf8562a --- /dev/null +++ b/types/commonmark/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +}