diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7654228 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +node_modules +/built +/coverage +/.eslintrc.js +/jest.config.ts +parser.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..a0f4374 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,32 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + ], + rules: { + 'indent': ['error', 'tab', { + 'SwitchCase': 1, + 'flatTernaryExpressions': true, + }], + 'eol-last': ['error', 'always'], + 'semi': ['error', 'always'], + 'quotes': ['error', 'single'], + 'keyword-spacing': ['error', { + 'before': true, + 'after': true, + }], + 'no-multi-spaces': ['error'], + 'no-var': ['error'], + 'prefer-arrow-callback': ['error'], + 'no-throw-literal': ['error'], + 'no-param-reassign': ['warn'], + 'no-constant-condition': ['warn'], + 'no-empty-pattern': ['warn'], + '@typescript-eslint/no-inferrable-types': ['warn'], + }, +}; diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ba46dfd..8384cfa 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,21 +1,29 @@ diff --git a/.github/workflows/api.yml b/.github/workflows/api.yml new file mode 100644 index 0000000..dcbc7c0 --- /dev/null +++ b/.github/workflows/api.yml @@ -0,0 +1,40 @@ +name: API report + +on: [push, pull_request] + +jobs: + report: + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 16.5.0 + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Check files + run: ls built + + - name: API report + run: npm run api-prod + + - name: Show report + if: always() + run: cat temp/mfm-js.api.md diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..cdf6d20 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,30 @@ +name: Lint + +on: [push, pull_request] + +jobs: + lint: + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 16.5.0 + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac5f86f..e072e19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,13 +1,9 @@ # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions -name: Test +name: Test and coverage -on: - push: - branches: [ develop ] - pull_request: - branches: [ develop ] +on: [push, pull_request] jobs: test: @@ -16,21 +12,34 @@ jobs: strategy: matrix: - node-version: [12.x, 16.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + node-version: [16.5.0] steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Install - run: npm i - - name: Build - run: npm run build - - name: Test - run: npm run test - - name: Upload Coverage - uses: codecov/codecov-action@v1 + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Test + run: npm test + env: + CI: true + + - name: Upload Coverage + uses: codecov/codecov-action@v1 diff --git a/api-extractor.json b/api-extractor.json new file mode 100644 index 0000000..a95281a --- /dev/null +++ b/api-extractor.json @@ -0,0 +1,364 @@ +/** + * Config file for API Extractor. For more info, please visit: https://api-extractor.com + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + + /** + * Optionally specifies another JSON config file that this file extends from. This provides a way for + * standard settings to be shared across multiple projects. + * + * If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains + * the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be + * resolved using NodeJS require(). + * + * SUPPORTED TOKENS: none + * DEFAULT VALUE: "" + */ + // "extends": "./shared/api-extractor-base.json" + // "extends": "my-package/include/api-extractor-base.json" + + /** + * Determines the "" token that can be used with other config file settings. The project folder + * typically contains the tsconfig.json and package.json config files, but the path is user-defined. + * + * The path is resolved relative to the folder of the config file that contains the setting. + * + * The default value for "projectFolder" is the token "", which means the folder is determined by traversing + * parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder + * that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error + * will be reported. + * + * SUPPORTED TOKENS: + * DEFAULT VALUE: "" + */ + // "projectFolder": "..", + + /** + * (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor + * analyzes the symbols exported by this module. + * + * The file extension must be ".d.ts" and not ".ts". + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + */ + "mainEntryPointFilePath": "/built/index.d.ts", + + /** + * A list of NPM package names whose exports should be treated as part of this package. + * + * For example, suppose that Webpack is used to generate a distributed bundle for the project "library1", + * and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part + * of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly + * imports library2. To avoid this, we can specify: + * + * "bundledPackages": [ "library2" ], + * + * This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been + * local files for library1. + */ + "bundledPackages": [], + + /** + * Determines how the TypeScript compiler engine will be invoked by API Extractor. + */ + "compiler": { + /** + * Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * Note: This setting will be ignored if "overrideTsconfig" is used. + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/tsconfig.json" + */ + // "tsconfigFilePath": "/tsconfig.json", + /** + * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk. + * The object must conform to the TypeScript tsconfig schema: + * + * http://json.schemastore.org/tsconfig + * + * If omitted, then the tsconfig.json file will be read from the "projectFolder". + * + * DEFAULT VALUE: no overrideTsconfig section + */ + // "overrideTsconfig": { + // . . . + // } + /** + * This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended + * and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when + * dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses + * for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck. + * + * DEFAULT VALUE: false + */ + // "skipLibCheck": true, + }, + + /** + * Configures how the API report file (*.api.md) will be generated. + */ + "apiReport": { + /** + * (REQUIRED) Whether to generate an API report. + */ + "enabled": true + + /** + * The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce + * a full file path. + * + * The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/". + * + * SUPPORTED TOKENS: , + * DEFAULT VALUE: ".api.md" + */ + // "reportFileName": ".api.md", + + /** + * Specifies the folder where the API report file is written. The file name portion is determined by + * the "reportFileName" setting. + * + * The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy, + * e.g. for an API review. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/etc/" + */ + // "reportFolder": "/etc/", + + /** + * Specifies the folder where the temporary report file is written. The file name portion is determined by + * the "reportFileName" setting. + * + * After the temporary file is written to disk, it is compared with the file in the "reportFolder". + * If they are different, a production build will fail. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/temp/" + */ + // "reportTempFolder": "/temp/" + }, + + /** + * Configures how the doc model file (*.api.json) will be generated. + */ + "docModel": { + /** + * (REQUIRED) Whether to generate a doc model file. + */ + "enabled": true + + /** + * The output path for the doc model file. The file extension should be ".api.json". + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/temp/.api.json" + */ + // "apiJsonFilePath": "/temp/.api.json" + }, + + /** + * Configures how the .d.ts rollup file will be generated. + */ + "dtsRollup": { + /** + * (REQUIRED) Whether to generate the .d.ts rollup file. + */ + "enabled": false + + /** + * Specifies the output path for a .d.ts rollup file to be generated without any trimming. + * This file will include all declarations that are exported by the main entry point. + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/dist/.d.ts" + */ + // "untrimmedFilePath": "/dist/.d.ts", + + /** + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release. + * This file will include only declarations that are marked as "@public" or "@beta". + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "betaTrimmedFilePath": "/dist/-beta.d.ts", + + /** + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release. + * This file will include only declarations that are marked as "@public". + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "publicTrimmedFilePath": "/dist/-public.d.ts", + + /** + * When a declaration is trimmed, by default it will be replaced by a code comment such as + * "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the + * declaration completely. + * + * DEFAULT VALUE: false + */ + // "omitTrimmingComments": true + }, + + /** + * Configures how the tsdoc-metadata.json file will be generated. + */ + "tsdocMetadata": { + /** + * Whether to generate the tsdoc-metadata.json file. + * + * DEFAULT VALUE: true + */ + // "enabled": true, + /** + * Specifies where the TSDoc metadata file should be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * The default value is "", which causes the path to be automatically inferred from the "tsdocMetadata", + * "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup + * falls back to "tsdoc-metadata.json" in the package folder. + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "tsdocMetadataFilePath": "/dist/tsdoc-metadata.json" + }, + + /** + * Specifies what type of newlines API Extractor should use when writing output files. By default, the output files + * will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead. + * To use the OS's default newline kind, specify "os". + * + * DEFAULT VALUE: "crlf" + */ + // "newlineKind": "crlf", + + /** + * Configures how API Extractor reports error and warning messages produced during analysis. + * + * There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages. + */ + "messages": { + /** + * Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing + * the input .d.ts files. + * + * TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551" + * + * DEFAULT VALUE: A single "default" entry with logLevel=warning. + */ + "compilerMessageReporting": { + /** + * Configures the default routing for messages that don't match an explicit rule in this table. + */ + "default": { + /** + * Specifies whether the message should be written to the the tool's output log. Note that + * the "addToApiReportFile" property may supersede this option. + * + * Possible values: "error", "warning", "none" + * + * Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail + * and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes + * the "--local" option), the warning is displayed but the build will not fail. + * + * DEFAULT VALUE: "warning" + */ + "logLevel": "warning" + + /** + * When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md), + * then the message will be written inside that file; otherwise, the message is instead logged according to + * the "logLevel" option. + * + * DEFAULT VALUE: false + */ + // "addToApiReportFile": false + } + + // "TS2551": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + }, + + /** + * Configures handling of messages reported by API Extractor during its analysis. + * + * API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag" + * + * DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings + */ + "extractorMessageReporting": { + "default": { + "logLevel": "none" + // "addToApiReportFile": false + } + + // "ae-extra-release-tag": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + }, + + /** + * Configures handling of messages reported by the TSDoc parser when analyzing code comments. + * + * TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text" + * + * DEFAULT VALUE: A single "default" entry with logLevel=warning. + */ + "tsdocMessageReporting": { + "default": { + "logLevel": "warning" + // "addToApiReportFile": false + } + + // "tsdoc-link-tag-unescaped-text": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + } + } +} diff --git a/etc/mfm-js.api.md b/etc/mfm-js.api.md new file mode 100644 index 0000000..3c5101a --- /dev/null +++ b/etc/mfm-js.api.md @@ -0,0 +1,268 @@ +## API Report File for "mfm-js" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public (undocumented) +export const BOLD: (children: MfmInline[]) => NodeType<'bold'>; + +// @public (undocumented) +export const CENTER: (children: MfmInline[]) => NodeType<'center'>; + +// @public (undocumented) +export const CODE_BLOCK: (code: string, lang: string | null) => NodeType<'blockCode'>; + +// @public (undocumented) +export const EMOJI_CODE: (name: string) => NodeType<'emojiCode'>; + +// @public (undocumented) +export function extract(nodes: MfmNode[], predicate: (node: MfmNode) => boolean): MfmNode[]; + +// @public (undocumented) +export const FN: (name: string, args: MfmFn['props']['args'], children: MfmFn['children']) => NodeType<'fn'>; + +// @public (undocumented) +export const HASHTAG: (value: string) => NodeType<'hashtag'>; + +// @public (undocumented) +export const INLINE_CODE: (code: string) => NodeType<'inlineCode'>; + +// @public (undocumented) +export function inspect(node: MfmNode, action: (node: MfmNode) => void): void; + +// @public (undocumented) +export function inspect(nodes: MfmNode[], action: (node: MfmNode) => void): void; + +// @public (undocumented) +export const ITALIC: (children: MfmInline[]) => NodeType<'italic'>; + +// @public (undocumented) +export const LINK: (silent: boolean, url: string, children: MfmInline[]) => NodeType<'link'>; + +// @public (undocumented) +export const MATH_BLOCK: (formula: string) => NodeType<'mathBlock'>; + +// @public (undocumented) +export const MATH_INLINE: (formula: string) => NodeType<'mathInline'>; + +// @public (undocumented) +export const MENTION: (username: string, host: string | null, acct: string) => NodeType<'mention'>; + +// @public (undocumented) +export type MfmBlock = MfmQuote | MfmSearch | MfmCodeBlock | MfmMathBlock | MfmCenter; + +// @public (undocumented) +export type MfmBold = { + type: 'bold'; + props?: Record; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmCenter = { + type: 'center'; + props?: Record; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmCodeBlock = { + type: 'blockCode'; + props: { + code: string; + lang: string | null; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmEmojiCode = { + type: 'emojiCode'; + props: { + name: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmFn = { + type: 'fn'; + props: { + name: string; + args: Record; + }; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmHashtag = { + type: 'hashtag'; + props: { + hashtag: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmText; + +// @public (undocumented) +export type MfmInlineCode = { + type: 'inlineCode'; + props: { + code: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmItalic = { + type: 'italic'; + props?: Record; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmLink = { + type: 'link'; + props: { + silent: boolean; + url: string; + }; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmMathBlock = { + type: 'mathBlock'; + props: { + formula: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmMathInline = { + type: 'mathInline'; + props: { + formula: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmMention = { + type: 'mention'; + props: { + username: string; + host: string | null; + acct: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmNode = MfmBlock | MfmInline; + +// @public (undocumented) +export type MfmQuote = { + type: 'quote'; + props?: Record; + children: MfmNode[]; +}; + +// @public (undocumented) +export type MfmSearch = { + type: 'search'; + props: { + query: string; + content: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmSmall = { + type: 'small'; + props?: Record; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmStrike = { + type: 'strike'; + props?: Record; + children: MfmInline[]; +}; + +// @public (undocumented) +export type MfmText = { + type: 'text'; + props: { + text: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmUnicodeEmoji = { + type: 'unicodeEmoji'; + props: { + emoji: string; + }; + children?: []; +}; + +// @public (undocumented) +export type MfmUrl = { + type: 'url'; + props: { + url: string; + brackets?: boolean; + }; + children?: []; +}; + +// @public (undocumented) +export const N_URL: (value: string, brackets?: boolean | undefined) => NodeType<'url'>; + +// @public (undocumented) +export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'text' ? MfmText : never; + +// @public (undocumented) +export function parse(input: string): MfmNode[]; + +// Warning: (ae-forgotten-export) The symbol "MfmPlainNode" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export function parsePlain(input: string): MfmPlainNode[]; + +// @public (undocumented) +export const QUOTE: (children: MfmNode[]) => NodeType<'quote'>; + +// @public (undocumented) +export const SEARCH: (query: string, content: string) => NodeType<'search'>; + +// @public (undocumented) +export const SMALL: (children: MfmInline[]) => NodeType<'small'>; + +// @public (undocumented) +export const STRIKE: (children: MfmInline[]) => NodeType<'strike'>; + +// @public (undocumented) +export const TEXT: (value: string) => NodeType<'text'>; + +// @public (undocumented) +function toString_2(tree: MfmNode[]): string; + +// @public (undocumented) +function toString_2(node: MfmNode): string; +export { toString_2 as toString } + +// @public (undocumented) +export const UNI_EMOJI: (value: string) => NodeType<'unicodeEmoji'>; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/package.json b/package.json index e60b69d..f561c02 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,9 @@ "tsd": "tsd", "parse": "node ./built/cli/parse", "parse-plain": "node ./built/cli/parsePlain", + "api": "npx api-extractor run --local --verbose", + "api-prod": "npx api-extractor run --verbose", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx", "jest": "jest --coverage", "test": "npm run jest && npm run tsd" }, @@ -24,9 +27,13 @@ "author": "Marihachi", "license": "MIT", "devDependencies": { + "@microsoft/api-extractor": "^7.18.4", "@types/jest": "^26.0.23", "@types/node": "15.12.4", + "@typescript-eslint/eslint-plugin": "^4.28.5", + "@typescript-eslint/parser": "^4.28.5", "copyfiles": "^2.4.1", + "eslint": "^7.32.0", "jest": "^27.0.5", "peggy": "1.2.0", "ts-jest": "^27.0.3", diff --git a/src/api.ts b/src/api.ts index 9dcddaf..3a72c5c 100644 --- a/src/api.ts +++ b/src/api.ts @@ -2,6 +2,7 @@ import peg from 'peggy'; import { MfmNode, MfmPlainNode } from './node'; import { stringifyNode, stringifyTree, inspectOne } from './internal/util'; +// eslint-disable-next-line @typescript-eslint/no-var-requires const parser: peg.Parser = require('./internal/parser'); /** diff --git a/src/cli/parse.ts b/src/cli/parse.ts index 556d69a..120df08 100644 --- a/src/cli/parse.ts +++ b/src/cli/parse.ts @@ -39,8 +39,9 @@ async function entryPoint() { console.log(); } } + entryPoint() -.catch(err => { - console.log(err); - process.exit(1); -}); + .catch(err => { + console.log(err); + process.exit(1); + }); diff --git a/src/cli/parsePlain.ts b/src/cli/parsePlain.ts index a1cab65..258f26c 100644 --- a/src/cli/parsePlain.ts +++ b/src/cli/parsePlain.ts @@ -39,8 +39,9 @@ async function entryPoint() { console.log(); } } + entryPoint() -.catch(err => { - console.log(err); - process.exit(1); -}); + .catch(err => { + console.log(err); + process.exit(1); + }); diff --git a/src/internal/util.ts b/src/internal/util.ts index 39ab597..d25c502 100644 --- a/src/internal/util.ts +++ b/src/internal/util.ts @@ -30,7 +30,7 @@ export function mergeText(nodes: (MfmNode | string)[]): MfmNode[] { } export function stringifyNode(node: MfmNode): string { - switch(node.type) { + switch (node.type) { // block case 'quote': { return stringifyTree(node.children).split('\n').map(line => `> ${line}`).join('\n'); @@ -114,10 +114,10 @@ enum stringifyState { none = 0, inline, block -}; +} export function stringifyTree(nodes: MfmNode[]): string { - let dest: MfmNode[] = []; + const dest: MfmNode[] = []; let state: stringifyState = stringifyState.none; for (const node of nodes) { diff --git a/src/node.ts b/src/node.ts index 03c8453..3f80b15 100644 --- a/src/node.ts +++ b/src/node.ts @@ -11,7 +11,7 @@ export function isMfmBlock(node: MfmNode): node is MfmBlock { export type MfmQuote = { type: 'quote'; - props?: { }; + props?: Record; children: MfmNode[]; }; export const QUOTE = (children: MfmNode[]): NodeType<'quote'> => { return { type:'quote', children }; }; @@ -47,7 +47,7 @@ export const MATH_BLOCK = (formula: string): NodeType<'mathBlock'> => { return { export type MfmCenter = { type: 'center'; - props?: { }; + props?: Record; children: MfmInline[]; }; export const CENTER = (children: MfmInline[]): NodeType<'center'> => { return { type:'center', children }; }; @@ -75,28 +75,28 @@ export const EMOJI_CODE = (name: string): NodeType<'emojiCode'> => { return { ty export type MfmBold = { type: 'bold'; - props?: { }; + props?: Record; children: MfmInline[]; }; export const BOLD = (children: MfmInline[]): NodeType<'bold'> => { return { type:'bold', children }; }; export type MfmSmall = { type: 'small'; - props?: { }; + props?: Record; children: MfmInline[]; }; export const SMALL = (children: MfmInline[]): NodeType<'small'> => { return { type:'small', children }; }; export type MfmItalic = { type: 'italic'; - props?: { }; + props?: Record; children: MfmInline[]; }; export const ITALIC = (children: MfmInline[]): NodeType<'italic'> => { return { type:'italic', children }; }; export type MfmStrike = { type: 'strike'; - props?: { }; + props?: Record; children: MfmInline[]; }; export const STRIKE = (children: MfmInline[]): NodeType<'strike'> => { return { type:'strike', children }; }; diff --git a/test/api.ts b/test/api.ts index 1af36ee..4799b6f 100644 --- a/test/api.ts +++ b/test/api.ts @@ -21,10 +21,10 @@ after`; }); it('preserve url brackets', () => { - const input1 = `https://github.com/syuilo/ai`; + const input1 = 'https://github.com/syuilo/ai'; assert.strictEqual(mfm.toString(mfm.parse(input1)), input1); - const input2 = ``; + const input2 = ''; assert.strictEqual(mfm.toString(mfm.parse(input2)), input2); }); }); diff --git a/test/parser.ts b/test/parser.ts index 489c821..88d62cd 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -123,7 +123,7 @@ describe('FullParser', () => { assert.deepStrictEqual(mfm.parse(input), output); }); it('1行の引用ブロックを空行にはできない', () => { - const input = `> `; + const input = '> '; const output = [ TEXT('> ') ];