diff --git a/.eslintrc.yaml b/.eslintrc.yaml index c5ec2a9..932521c 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -15,28 +15,17 @@ parserOptions: ecmaVersion: 2018 project: "./tsconfig.eslint.json" rules: - # TODO turn the following on after updating repo - "@typescript-eslint/naming-convention": "off" + + # these are related to using any "@typescript-eslint/no-unsafe-member-access": "off" "@typescript-eslint/no-unsafe-assignment": "off" - "@typescript-eslint/no-floating-promises": "off" "@typescript-eslint/restrict-template-expressions": "off" - "@typescript-eslint/no-unsafe-return": "off" "@typescript-eslint/explicit-module-boundary-types": "off" - "@typescript-eslint/restrict-plus-operands": "off" - "@typescript-eslint/no-unsafe-call": "off" - "@typescript-eslint/ban-types": "off" - # end TODO + "@typescript-eslint/no-explicit-any": "off" + no-undef: "off" no-unused-vars: "off" no-constant-condition: "off" - "@typescript-eslint/ban-ts-comment": error - "@typescript-eslint/prefer-interface": "off" - "@typescript-eslint/explicit-function-return-type": "off" - "@typescript-eslint/explicit-member-accessibility": "off" - "@typescript-eslint/indent": "off" - "@typescript-eslint/interface-name-prefix": "off" - "@typescript-eslint/no-use-before-define": "off" "@typescript-eslint/type-annotation-spacing": - error - before: false @@ -52,10 +41,6 @@ rules: prefer-arrow-callback: - error - allowUnboundThis: false - "@typescript-eslint/no-parameter-properties": "off" - "@typescript-eslint/no-explicit-any": "off" - "@typescript-eslint/no-inferrable-types": "off" - "@typescript-eslint/prefer-regexp-exec": "off" "@typescript-eslint/no-empty-function": "off" "@typescript-eslint/no-misused-promises": - error diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7147bfd..74b911e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,13 +53,11 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: Compile + - name: Build Package run: | npm ci - npm run compile - - name: Build Grammar - run: npm run build - # TODO test built files don't change after this? + npm run build + # TODO test built grammar files don't change after this? - name: Run tests uses: GabrielBB/xvfb-action@v1.0 with: @@ -78,4 +76,4 @@ jobs: with: args: "publish -p $VSCE_TOKEN" env: - VSCE_TOKEN: ${{ secrets.VSCE_PUB }} \ No newline at end of file + VSCE_TOKEN: ${{ secrets.VSCE_PUB }} diff --git a/.gitignore b/.gitignore index a632f9d..0785de9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ out node_modules +.DS_Store .vscode-test/ *.vsix .eslintcache .vscode/ +_archive/ diff --git a/.vscodeignore b/.vscodeignore index 7e0be89..bcb66e3 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -6,6 +6,7 @@ src/** vsc-extension-quickstart.md **/tsconfig.json **/tslint.json +**/.eslintcache **/*.map **/*.ts _archive/** diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8d67f79 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Change Log + +## v0.11.0 - 2021-07-10 + +This version marks a complete re-write of the Markdown preview extension, to more fully support the MyST syntax: + +- Full rendering of many common directives, including: all core admonitions, `image`, `figure`, `code`, `code-block`, `code-cell`, `list-table`. +- Fixes previous issues with admonition renderings. +- Support for MyST syntax extensions via the `myst.preview.extensions` [configuration setting][vscode-settings]: `amsmath`, `colon_fence`, `deflist`, `dollarmath` (default), `tasklist` + +See the README for more details! + +Under the hood, the version also marks a large number of changes, to improve the maintenance and documentation of the extension, and to use a number of new external markdown-it plugin libraries, such as [markdown-it-docutils](https://github.com/executablebooks/markdown-it-docutils). + +[vscode-settings]: https://code.visualstudio.com/docs/getstarted/settings diff --git a/README.md b/README.md index c981e65..87194e7 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,31 @@ -# myst-language-support +# MyST-Markdown VS Code Extension [![VS Marketplace][vs-market-badge]][vs-market-link] [![Github-CI][github-ci-badge]][github-ci-link] -The official [MyST (Markedly Structured Text)](https://myst-parser.readthedocs.io) Textmate grammar, and VS Code extension, for extending the markdown language. +The official [MyST (Markedly Structured Text)](https://myst-parser.readthedocs.io) VS Code extension, for extending the Markdown language. -This extension injects additional elements into the base markdown syntax highlighting grammar, -and adds additional language support for MyST specific elements. +This extension extends VS Code's Markdown language with the following features: -**Important** This extension is a work in progress, and future changes are likely. +- Extended syntax highlighting +- Hover information and auto-completion for roles and directives +- Extended preview rendering +- Code snippets for role and directive definitions -- [myst-language-support](#myst-language-support) +injects additional elements into the base markdown syntax highlighting grammar, and adds additional language support for MyST specific elements. + +- [MyST-Markdown VS Code Extension](#myst-markdown-vs-code-extension) - [Features](#features) - [Syntax Highlighting](#syntax-highlighting) - [Hover and Autocompletion](#hover-and-autocompletion) - [Preview Enhancement](#preview-enhancement) + - [CSS Styling](#css-styling) + - [A note on dollar-math](#a-note-on-dollar-math) - [Working with Markdown](#working-with-markdown) - [Contributing](#contributing) - - [Building the Grammar](#building-the-grammar) - - [Testing](#testing) + - [Manual testing](#manual-testing) + - [Building the grammar and snippet assets](#building-the-grammar-and-snippet-assets) + - [Unit and integration testing](#unit-and-integration-testing) - [Linting](#linting) - [Publishing to VS Marketplace](#publishing-to-vs-marketplace) - [Acknowledgements](#acknowledgements) @@ -27,67 +34,96 @@ and adds additional language support for MyST specific elements. ### Syntax Highlighting -screenshot +screenshot Embedded code blocks/cells can be utilised in their native language: -screenshot +screenshot ### Hover and Autocompletion Directive completion and hover is available for all built-in sphinx directives: -screenshot +screenshot -screenshot +screenshot Snippet completions are also available for a number of Sphinx directives: -screenshot +screenshot ### Preview Enhancement This extension enhances VS Code's built-in Markdown previewer -([see this guide for info](https://code.visualstudio.com/api/extension-guides/markdown-extension)), -to properly render nested admonitions, and code directives, etc. +([see this guide for info](https://code.visualstudio.com/api/extension-guides/markdown-extension)), to properly render MyST syntax like directives and other extensions. + +screenshot + +If you encounter any issues with this, you can disable it with the `myst.preview.enable` [configuration setting][vscode-settings] (and please report it). + +You can add MyST syntax extensions with the `myst.preview.extensions` [configuration setting][vscode-settings]. Available extensions: + +- `amsmath`: Parse AMS LaTeX math environments +- `deflist`: Parse definition lists +- `dollarmath`: Parse dollar-delimited math (on by default) +- `tasklist`: Parse GitHub style task lists + +Note after changing this setting you should reload the VS Code window. + +#### CSS Styling -screenshot +Principally the stylings from [markdown-it-docutils](https://github.com/executablebooks/markdown-it-docutils) are used. -If you encounter any issues with this, you can disable it -with the `myst.preview.enable` configuration option -(and please report it). +The colors are in light mode by default, switching to the dark mode when set by the users operating system. +See the [`prefers-color-scheme` documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) for details. + +#### A note on dollar-math + +From VS Code version `v1.58.0`, VS Code natively supports dollar math rendering ([see here](https://code.visualstudio.com/updates/v1_58#_math-formula-rendering-in-the-markdown-preview)). +Using the `dollarmath` extension overrides this with some slightly different parsing rules (e.g. dollarmath allows `$$` display math in inline contexts and also labels: `$$a=1$$ (label)`). + +If there are still any incompatibilities you can turn off the native support with `markdown.math.enabled` [configuration setting][vscode-settings]. ## Working with Markdown Here are some useful editor keyboard shortcuts: -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux) -* Toggle preview (`Shift+CMD+V` on macOS or `Shift+Ctrl+V` on Windows and Linux) -* Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (macOS) to see a list of Markdown snippets +- Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux) +- Toggle preview (`Shift+CMD+V` on macOS or `Shift+Ctrl+V` on Windows and Linux) +- Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (macOS) to see a list of Markdown snippets For more information: -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) +- [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) +- [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) ## Contributing The main grammar is stored in `syntaxes/myst.tmLanguage`. This file is generated from `myst.tmLanguage.base.yaml`. -See [this guide on textmate bundles](https://macromates.com/manual/en/language_grammars) and -[the VS Code guide](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide) for more help. +See [this guide on textmate bundles](https://macromates.com/manual/en/language_grammars), the [VS Code Syntax Highlight guide](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide), and the [extension API](https://code.visualstudio.com/api) for more help. + +### Manual testing + +To launch a local version of the extension in VS Code, first ensure the extension build is updated: + +```console +$ npm run build +``` + +Now select the `Launch Extension` configuration in the VS Code `Run and Debug` side panel. +To launch a development version of the extension in VS Code, press `F5`. -### Building the Grammar +### Building the grammar and snippet assets -The grammar is written as a [jinja template](https://jinja.palletsprojects.com) YAML file, +The grammar is written as a [Jinja template](https://jinja.palletsprojects.com) YAML file, with the templates and default variables stored in `template/` -To generate the main grammar with javascript: +To generate the asset files (grammar and snippets): ```bash $ npm ci -$ npm run compile -$ npm run build +$ npm run build:assets ``` or with python: @@ -97,34 +133,29 @@ $ pip install yaml jinja2 $ python src/build.py ``` -Snippets are also built in the same manner. +### Unit and integration testing -### Testing +The test suite is split into: -To run the full test suite: - -```bash -$ npm test -``` +- 'integration' tests, which require VS Code to be launched, and +- 'unit' tests, which can be run in the standard fashion with [mocha](https://mochajs.org) -The test suite is split into 'integration' tests, -which require VS Code to be launched, -and 'standalone' tests, -which can be run in the standard fashion with [mocha](https://mochajs.org). +You can run them on the CLI with `npm test`, or separately: ```bash $ npm run pretest -$ node ./out/test/runIntergration.js -$ ./node_modules/mocha/bin/mocha --ui tdd out/test/standalone/ +$ npm run test:unit +$ npm run test:integration ``` -The highlighting test cases are stored as markdown files under `test_static/colorize-fixtures`. -Grammar test results are stored under `test_static/colorize-results`, which are automatically generated/updated from the fixtures. +Running from the CLI will download and launch a specific version of VS Code (see `src/test/runIntergration.ts`). -To visualise the grammar in VS Code, select the `Launch Extension` configuration in the VS Code debugger and run. -To launch a development version of the extension in VS Code, press `F5`. +Note though, that running integration tests from within VS Code may error (see [Testing extensions tips](https://code.visualstudio.com/api/working-with-extensions/testing-extension#using-insiders-version-for-extension-development)). +In this case you can run the tests directly through the `Debug Launcher` in the side panel (see `.vscode/launch.json`). The output can be viewed in the debug console. -See also [VS Code Testing Extension Guide](https://code.visualstudio.com/api/working-with-extensions/testing-extension) +The highlighting test cases are stored as markdown files under `test_static/colorize-fixtures`. +Grammar test results are stored under `test_static/colorize-results`, which are automatically generated/updated from the fixtures. +Note though that the fixture results can change between VS Code versions, so you should use the version specified in `src/test/runIntergration.ts`. ### Linting @@ -140,16 +171,23 @@ $ npm run lint:fix ### Publishing to VS Marketplace -The publishing of the package should be done *via* the Github Actions CI. To trigger a release, bump the version in `package.json`, and create a new release tag on Github -starting with `release`, e.g. `release-0.9.4`. +The publishing of the package should be done *via* the Github Actions CI. +To trigger a release: + +1. Bump the version with npm, e.g. `npm version patch -m "🚀 RELEASE: v%s"` (major/minor/patch based on [semantic versioning](https://semver.org/)) +2. Push the commit and tag generated by npm (`git push --follow-tags`) +3. Create a new release tag on Github starting with `release`, e.g. `release-0.9.4`. -See: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#publishing-extensions +See also: ## Acknowledgements Testing originally adapted from [vscode-markdown-tm-grammar](https://github.com/microsoft/vscode-markdown-tm-grammar/tree/59a5962e4775bf96484bba64c5322422b555a40d). +VS Code Markdown extension exemplars were taken from [vscode/extensions/markdown-math](https://github.com/microsoft/vscode/blob/main/extensions/markdown-math). + [vs-market-badge]: https://vsmarketplacebadge.apphb.com/version/ExecutableBookProject.myst-highlight.svg "Current Release" [vs-market-link]: https://marketplace.visualstudio.com/items?itemName=ExecutableBookProject.myst-highlight -[github-ci-badge]: https://img.shields.io/github/workflow/status/ExecutableBookProject/myst-highlight-grammar/Github-CI?label=Github-CI -[github-ci-link]: https://github.com/ExecutableBookProject/myst-highlight-grammar/actions \ No newline at end of file +[github-ci-badge]: https://img.shields.io/github/workflow/status/ExecutableBookProject/myst-language-support/Github-CI?label=Github-CI +[github-ci-link]: https://github.com/ExecutableBookProject/myst-language-support/actions +[vscode-settings]: https://code.visualstudio.com/docs/getstarted/settings diff --git a/_archive/build.js b/_archive/build.js deleted file mode 100644 index 5d70706..0000000 --- a/_archive/build.js +++ /dev/null @@ -1,196 +0,0 @@ -// @ts-check - -const fs = require('fs'); -const path = require('path'); -const yaml = require('js-yaml'); -const plist = require('plist'); - -const languages = [ - { name: 'css', language: 'css', identifiers: ['css', 'css.erb'], source: 'source.css' }, - { name: 'basic', language: 'html', identifiers: ['html', 'htm', 'shtml', 'xhtml', 'inc', 'tmpl', 'tpl'], source: 'text.html.basic' }, - { name: 'ini', language: 'ini', identifiers: ['ini', 'conf'], source: 'source.ini' }, - { name: 'java', language: 'java', identifiers: ['java', 'bsh'], source: 'source.java' }, - { name: 'lua', language: 'lua', identifiers: ['lua'], source: 'source.lua' }, - { name: 'makefile', language: 'makefile', identifiers: ['Makefile', 'makefile', 'GNUmakefile', 'OCamlMakefile'], source: 'source.makefile' }, - { name: 'perl', language: 'perl', identifiers: ['perl', 'pl', 'pm', 'pod', 't', 'PL', 'psgi', 'vcl'], source: 'source.perl' }, - { name: 'r', language: 'r', identifiers: ['R', 'r', 's', 'S', 'Rprofile', '\\{\\.r.+?\\}'], source: 'source.r' }, - { name: 'ruby', language: 'ruby', identifiers: ['ruby', 'rb', 'rbx', 'rjs', 'Rakefile', 'rake', 'cgi', 'fcgi', 'gemspec', 'irbrc', 'Capfile', 'ru', 'prawn', 'Cheffile', 'Gemfile', 'Guardfile', 'Hobofile', 'Vagrantfile', 'Appraisals', 'Rantfile', 'Berksfile', 'Berksfile.lock', 'Thorfile', 'Puppetfile'], source: 'source.ruby' }, - // Left to its own devices, the PHP grammar will match HTML as a combination of operators - // and constants. Therefore, HTML must take precedence over PHP in order to get proper - // syntax highlighting. - { name: 'php', language: 'php', identifiers: ['php', 'php3', 'php4', 'php5', 'phpt', 'phtml', 'aw', 'ctp'], source: ['text.html.basic', 'source.php'] }, - { name: 'sql', language: 'sql', identifiers: ['sql', 'ddl', 'dml'], source: 'source.sql' }, - { name: 'vs_net', language: 'vs_net', identifiers: ['vb'], source: 'source.asp.vb.net' }, - { name: 'xml', language: 'xml', identifiers: ['xml', 'xsd', 'tld', 'jsp', 'pt', 'cpt', 'dtml', 'rss', 'opml'], source: 'text.xml' }, - { name: 'xsl', language: 'xsl', identifiers: ['xsl', 'xslt'], source: 'text.xml.xsl' }, - { name: 'yaml', language: 'yaml', identifiers: ['yaml', 'yml'], source: 'source.yaml' }, - { name: 'dosbatch', language: 'dosbatch', identifiers: ['bat', 'batch'], source: 'source.batchfile' }, - { name: 'clojure', language: 'clojure', identifiers: ['clj', 'cljs', 'clojure'], source: 'source.clojure' }, - { name: 'coffee', language: 'coffee', identifiers: ['coffee', 'Cakefile', 'coffee.erb'], source: 'source.coffee' }, - { name: 'c', language: 'c', identifiers: ['c', 'h'], source: 'source.c' }, - { name: 'cpp', language: 'cpp', identifiers: ['cpp', 'c\\+\\+', 'cxx'], source: 'source.cpp', additionalContentName: ['source.cpp'] }, - { name: 'diff', language: 'diff', identifiers: ['patch', 'diff', 'rej'], source: 'source.diff' }, - { name: 'dockerfile', language: 'dockerfile', identifiers: ['dockerfile', 'Dockerfile'], source: 'source.dockerfile' }, - { name: 'git_commit', identifiers: ['COMMIT_EDITMSG', 'MERGE_MSG'], source: 'text.git-commit' }, - { name: 'git_rebase', identifiers: ['git-rebase-todo'], source: 'text.git-rebase' }, - { name: 'go', language: 'go', identifiers: ['go', 'golang'], source: 'source.go' }, - { name: 'groovy', language: 'groovy', identifiers: ['groovy', 'gvy'], source: 'source.groovy' }, - { name: 'pug', language: 'pug', identifiers: ['jade', 'pug'], source: 'text.pug' }, - - { name: 'js', language: 'javascript', identifiers: ['js', 'jsx', 'javascript', 'es6', 'mjs', 'cjs', '\\{\\.js.+?\\}'], source: 'source.js' }, - { name: 'js_regexp', identifiers: ['regexp'], source: 'source.js.regexp' }, - { name: 'json', language: 'json', identifiers: ['json', 'json5', 'sublime-settings', 'sublime-menu', 'sublime-keymap', 'sublime-mousemap', 'sublime-theme', 'sublime-build', 'sublime-project', 'sublime-completions'], source: 'source.json' }, - { name: 'jsonc', language: 'jsonc', identifiers: ['jsonc'], source: 'source.json.comments' }, - { name: 'less', language: 'less', identifiers: ['less'], source: 'source.css.less' }, - { name: 'objc', language: 'objc', identifiers: ['objectivec', 'objective-c', 'mm', 'objc', 'obj-c', 'm', 'h'], source: 'source.objc' }, - { name: 'swift', language: 'swift', identifiers: ['swift'], source: 'source.swift' }, - { name: 'scss', language: 'scss', identifiers: ['scss'], source: 'source.css.scss' }, - - { name: 'perl6', language: 'perl6', identifiers: ['perl6', 'p6', 'pl6', 'pm6', 'nqp'], source: 'source.perl.6' }, - { name: 'powershell', language: 'powershell', identifiers: ['powershell', 'ps1', 'psm1', 'psd1'], source: 'source.powershell' }, - { name: 'python', language: 'python', identifiers: ['python', 'py', 'py3', 'rpy', 'pyw', 'cpy', 'SConstruct', 'Sconstruct', 'sconstruct', 'SConscript', 'gyp', 'gypi', '\\{\\.python.+?\\}'], source: 'source.python' }, - { name: 'ipython', language: 'python', identifiers: ['ipython', 'ipython2', 'ipython3', '\\{\\.ipython.+?\\}'], source: 'source.python' }, - { name: 'regexp_python', identifiers: ['re'], source: 'source.regexp.python' }, - { name: 'rust', language: 'rust', identifiers: ['rust', 'rs', '\\{\\.rust.+?\\}'], source: 'source.rust' }, - { name: 'scala', language: 'scala', identifiers: ['scala', 'sbt'], source: 'source.scala' }, - { name: 'shell', language: 'shellscript', identifiers: ['shell', 'sh', 'bash', 'zsh', 'bashrc', 'bash_profile', 'bash_login', 'profile', 'bash_logout', '.textmate_init', '\\{\\.bash.+?\\}'], source: 'source.shell' }, - { name: 'ts', language: 'typescript', identifiers: ['typescript', 'ts'], source: 'source.ts' }, - { name: 'tsx', language: 'typescriptreact', identifiers: ['tsx'], source: 'source.tsx' }, - { name: 'csharp', language: 'csharp', identifiers: ['cs', 'csharp', 'c#'], source: 'source.cs' }, - { name: 'fsharp', language: 'fsharp', identifiers: ['fs', 'fsharp', 'f#'], source: 'source.fsharp' }, - { name: 'dart', language: 'dart', identifiers: ['dart'], source: 'source.dart' }, - { name: 'handlebars', language: 'handlebars', identifiers: ['handlebars', 'hbs'], source: 'text.html.handlebars' }, - { name: 'markdown', language: 'markdown', identifiers: ['markdown', 'md'], source: 'text.html.markdown' }, - { name: 'log', language: 'log', identifiers: ['log'], source: 'text.log' } -]; - - -const fencedCodeBlockInclude = (name) => - `- { include: '#fenced_code_block_${name}' }`; - - -const fencedCodeBlockIncludes = () => -languages - .map(language => fencedCodeBlockInclude(language.name)) - .join('\n'); - - -const fencedCodeBlockDefinition = (name, identifiers, sourceScope, language, additionalContentName) => { - if (!Array.isArray(sourceScope)) { - sourceScope = [sourceScope]; - } - - language = language || name - - const scopes = sourceScope.map(scope => - `- { include: '${scope}' }`).join('\n'); - - let contentName = `meta.embedded.block.${language}`; - if (additionalContentName) { - contentName += ` ${additionalContentName.join(' ')}`; - } - - return `fenced_code_block_${name}: - begin: - (^|\\G)(\\s*)(\`{3,}|~{3,})\\s*(?i:(${identifiers.join('|')})((\\s+|:|\\{)[^\`~]*)?$) - name: - markup.fenced_code.block.myst - end: - (^|\\G)(\\2|\\s{0,3})(\\3)\\s*$ - beginCaptures: - '3': {name: 'punctuation.definition.myst'} - '4': {name: 'support.variable.language.myst'} - '5': {name: 'fenced_code.block.language.attributes.myst'} - endCaptures: - '3': {name: 'punctuation.definition.myst'} - patterns: - - begin: (^|\\G)(\\s*)(.*) - while: (^|\\G)(?!\\s*([\`~]{3,})\\s*$) - contentName: ${contentName} - patterns: -${indent(4, scopes)} -`; -}; - - -const fencedCodeBlockDefinitions = () => - languages - .map(language => fencedCodeBlockDefinition(language.name, language.identifiers, language.source, language.language, language.additionalContentName)) - .join('\n'); - - -const indent = (count, text) => { - const indent = new Array(count + 1).join(' '); - return text.replace(/^/gm, indent); -}; - - -const codeCellBlockInclude = (name) => - `- { include: '#code_cell_block_${name}' }`; - - -const codeCellBlockIncludes = () => -languages - .map(language => codeCellBlockInclude(language.name)) - .join('\n'); - - -const codeCellBlockDefinition = (name, identifiers, sourceScope, language, additionalContentName) => { - if (!Array.isArray(sourceScope)) { - sourceScope = [sourceScope]; - } - - language = language || name - - const scopes = sourceScope.map(scope => - `- { include: '${scope}' }`).join('\n'); - - let contentName = `meta.embedded.block.${language}`; - if (additionalContentName) { - contentName += ` ${additionalContentName.join(' ')}`; - } - - return `code_cell_block_${name}: - begin: - (^|\\G)(\\s*)(\`{3,}|~{3,})\\s*\\{(code-cell|code|code-block)\\}\\s+(?i:(${identifiers.join('|')})((\\s+|:|\\{)[^\`~]*)?$) - - name: - markup.code_cell.block.myst - end: - (^|\\G)(\\2|\\s{0,3})(\\3)\\s*$ - beginCaptures: - '3': {name: 'punctuation.definition.myst'} - '4': {name: 'support.class.directive.myst'} - '5': {name: 'support.variable.language.myst'} - '6': {name: 'directive.block.language.attributes.myst'} - endCaptures: - '3': {name: 'punctuation.definition.myst'} - patterns: - - begin: (^|\\G)(\\s*)(.*) - while: (^|\\G)(?!\\s*([\`~]{3,})\\s*$) - contentName: ${contentName} - patterns: -${indent(4, scopes)} -`; -}; - - -const codeCellBlockDefinitions = () => - languages - .map(language => codeCellBlockDefinition(language.name, language.identifiers, language.source, language.language, language.additionalContentName)) - .join('\n'); - - -const buildGrammar = () => { - let text = fs.readFileSync(path.join(__dirname, 'myst.tmLanguage.base.yaml'), "utf8"); - // text = text.replace(/\s*\{\{languageIncludes\}\}/, '\n' + indent(2, fencedCodeBlockIncludes())) - // text = text.replace(/\s*\{\{languageDefinitions\}\}/, '\n' + indent(1, fencedCodeBlockDefinitions())) - // text = text.replace(/\s*\{\{codeCellIncludes\}\}/, '\n' + indent(2, codeCellBlockIncludes())) - // text = text.replace(/\s*\{\{codeCellDefinitions\}\}/, '\n' + indent(1, codeCellBlockDefinitions())) - - const grammar = yaml.safeLoad(text); - const out = plist.build(grammar); - fs.writeFileSync(path.join(__dirname, 'syntaxes', 'myst.tmLanguage'), out); -}; - -buildGrammar(); diff --git a/_archive/extension.test.ts.txt b/_archive/extension.test.ts.txt deleted file mode 100644 index 8a6fcd5..0000000 --- a/_archive/extension.test.ts.txt +++ /dev/null @@ -1,22 +0,0 @@ -// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// The module 'assert' provides assertion methods from node -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -// import * as vscode from 'vscode'; -// import * as myExtension from '../extension'; - -// Defines a Mocha test suite to group tests of similar kind together -suite("Extension Tests", function () { - - // Defines a Mocha unit test - test("Something 2", function() { - assert.equal(-1, [1, 2, 3].indexOf(5)); - assert.equal(-1, [1, 2, 3].indexOf(0)); - }); -}); \ No newline at end of file diff --git a/_archive/language-configuration.json b/_archive/language-configuration.json deleted file mode 100644 index 5b7b4c8..0000000 --- a/_archive/language-configuration.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comments": { - // symbol used for single line comment. Remove this entry if your language does not support line comments - "lineComment": "%", - // symbols used for start and end a block comment. Remove this entry if your language does not support block comments - // "blockComment": [ "/*", "*/" ] - }, - // symbols used as brackets - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - // symbols that are auto closed when typing - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - // symbols that that can be used to surround a selection - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "folding": { - "markers": { - "start": "^`{3,}[^\\s]+", - "end": "^`{3,}\\s*$" - } - }, - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)" -} \ No newline at end of file diff --git a/_archive/myst.tmLanguage.base.yaml b/_archive/myst.tmLanguage.base.yaml deleted file mode 100644 index 66d6b2c..0000000 --- a/_archive/myst.tmLanguage.base.yaml +++ /dev/null @@ -1,507 +0,0 @@ -fileTypes: [myst, md, mdown, markdown, markdn] -keyEquivalent: ^~M -name: MyST Markdown -patterns: -- {include: '#frontMatter'} -- {include: '#block'} -repository: - block: - patterns: - - {include: '#line-comment'} - - {include: '#block-break'} - - {include: '#separator'} - - {include: '#heading'} - - {include: '#blockquote'} - - {include: '#lists'} - - {include: '#directive_block'} - - {include: '#fenced_code_block'} - - {include: '#raw_block'} - - {include: '#link-def'} - - {include: '#html'} - - {include: '#paragraph'} - heading: - match: (?:^|\G)[ ]{0,3}((#{1,6})\s+(?=[\S[^#]]).*?\s*(#{1,6})?)$\n? - captures: - '1': - patterns: - - match: (#{6})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.6.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - - match: (#{5})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.5.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - - match: (#{4})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.4.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - - match: (#{3})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.3.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - - match: (#{2})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.2.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - - match: (#{1})\s+(?=[\S[^#]])(.*?)\s*(\s+#+)?$\n? - name: 'heading.1.myst' - captures: - '1': {name: punctuation.definition.heading.myst} - '2': {name: entity.name.section.myst} - '3': {name: punctuation.definition.heading.myst} - name: markup.heading.myst - patterns: - - {include: '#inline'} - heading-setext: - patterns: - - {match: '^(={3,})(?=[ \t]*$\n?)', name: markup.heading.setext.1.myst} - - {match: '^(-{3,})(?=[ \t]*$\n?)', name: markup.heading.setext.2.myst} - html: - patterns: - - begin: (^|\G)\s*() - name: comment.block.html - - begin: (?i)(^|\G)\s*(?=<(script|style|pre)(\s|$|>)(?!.*?)) - end: (?i)(.*)(()) - endCaptures: - '1': { patterns: [ {include: text.html.derivative} ]} - '2': {name: meta.tag.structure.$4.end.html} - '3': {name: punctuation.definition.tag.begin.html} - '4': {name: entity.name.tag.html} - '5': {name: punctuation.definition.tag.end.html} - patterns: - - begin: (\s*|$) - patterns: - - {include: text.html.derivative} - while: (?i)^(?!.*) - - begin: (?i)(^|\G)\s*(?=)) - patterns: - - {include: text.html.derivative} - while: ^(?!\s*$) - - begin: (^|\G)\s*(?=(<[a-zA-Z0-9\-](/?>|\s.*?>)|)\s*$) - patterns: - - {include: text.html.derivative} - while: ^(?!\s*$) - link-def: - captures: - '1': {name: punctuation.definition.constant.myst} - '10': {name: punctuation.definition.string.end.myst} - '11': {name: string.other.link.description.title.myst} - '12': {name: punctuation.definition.string.begin.myst} - '13': {name: punctuation.definition.string.end.myst} - '2': {name: constant.other.reference.link.myst} - '3': {name: punctuation.definition.constant.myst} - '4': {name: punctuation.separator.key-value.myst} - '5': {name: punctuation.definition.link.myst} - '6': {name: markup.underline.link.myst} - '7': {name: punctuation.definition.link.myst} - '8': {name: string.other.link.description.title.myst} - '9': {name: punctuation.definition.string.begin.myst} - match: > - (?x) - \s* # Leading whitespace - (\[)([^]]+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in quotes… - | ((").+?(")) # or in parens. - )? # Title is optional - \s* # Optional whitespace - $ - name: meta.link.reference.def.myst - list_paragraph: - begin: (^|\G)(?=\S)(?![*+->]\s|[0-9]+\.\s) - name: meta.paragraph.myst - patterns: - - {include: '#inline'} - - {include: text.html.derivative} - - {include: '#heading-setext'} - while: (^|\G)(?!\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \t]*$\n?|[ ]{0,3}[*+->]|[ - ]{0,3}[0-9]+\.) - lists: - patterns: - - begin: (^|\G)([ ]{0,3})([*+-])([ \t]) - beginCaptures: - '3': {name: punctuation.definition.list.begin.myst} - comment: Currently does not support un-indented second lines. - name: markup.list.unnumbered.myst - patterns: - - {include: '#block'} - - {include: '#list_paragraph'} - while: ((^|\G)([ ]{2,4}|\t))|(^[ \t]*$) - - begin: (^|\G)([ ]{0,3})([0-9]+\.)([ \t]) - beginCaptures: - '3': {name: punctuation.definition.list.begin.myst} - name: markup.list.numbered.myst - patterns: - - {include: '#block'} - - {include: '#list_paragraph'} - while: ((^|\G)([ ]{2,4}|\t))|(^[ \t]*$) - paragraph: - begin: (^|\G)[ ]{0,3}(?=\S) - name: meta.paragraph.myst - patterns: - - {include: '#inline'} - - {include: text.html.derivative} - - {include: '#heading-setext'} - while: (^|\G)((?=\s*[-=]{3,}\s*$)|[ ]{4,}(?=\S)) - raw_block: {begin: '(^|\G)([ ]{4}|\t)', name: markup.raw.block.myst, while: '(^|\G)([ - ]{4}|\t)'} - separator: {match: '(^|\G)[ ]{0,3}([\*\-\_])([ ]{0,2}\2){2,}[ \t]*$\n?', name: meta.separator.myst} - line-comment: {match: '(^|\G)[ ]{0,3}\%\s*(.*)', name: comment.line.percentage} - block-break: - match: '(?:^|\G)[ ]{0,3}(\+\+\++)\s*(.*)' - captures: - '1': {name: keyword.other.myst} - '2': {name: meta.raw.myst} # TODO include source.json - frontMatter: - begin: \A-{3}\s*$ - contentName: meta.embedded.block.frontmatter - patterns: - - {include: source.yaml} - end: (^|\G)-{3}|\.{3}\s*$ - inline: - patterns: - - {include: '#ampersand'} - - {include: '#bracket'} - - {include: '#bold'} - - {include: '#italic'} - - {include: '#raw'} - - {include: '#escape'} - - {include: '#image-inline'} - - {include: '#image-ref'} - - {include: '#link-email'} - - {include: '#link-inet'} - - {include: '#link-inline'} - - {include: '#link-ref'} - - {include: '#link-ref-literal'} - - {include: '#link-ref-shortcut'} - ampersand: - comment: "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid." - match: '&(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)' - name: meta.other.valid-ampersand.myst - bold: - begin: > - (?x) - (?(\*\*(?=\w)|(?]*+> # HTML tags - | (?`+)([^`]|(?!(?(?!`))`)*+\k - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (? # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whitespace - ? # URL - [ \t]*+ # Optional whitespace - ( # Optional Title - (?['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | (?!(?<=\S)\k<open>). # Everything besides - # style closer - )++ - (?<=\S)(?=__\b|\*\*)\k<open> # Close - ) - captures: - '1': {name: punctuation.definition.bold.myst} - end: (?<=\S)(\1) - name: markup.bold.myst - patterns: - - applyEndPatternLast: 1 - begin: (?=<[^>]*?>) - end: (?<=>) - patterns: - - {include: text.html.derivative} - - {include: '#escape'} - - {include: '#ampersand'} - - {include: '#bracket'} - - {include: '#raw'} - - {include: '#bold'} - - {include: '#italic'} - - {include: '#image-inline'} - - {include: '#link-inline'} - - {include: '#link-inet'} - - {include: '#link-email'} - - {include: '#image-ref'} - - {include: '#link-ref-literal'} - - {include: '#link-ref'} - - {include: '#link-ref-shortcut'} - bracket: - comment: "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid." - match: '<(?![a-zA-Z/?\$!])' - name: meta.other.valid-bracket.myst - escape: {match: '\\[-`*_#+.!(){}\[\]\\>]', name: constant.character.escape.myst} - image-inline: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '10': {name: punctuation.definition.string.myst} - '11': {name: punctuation.definition.string.myst} - '12': {name: string.other.link.description.title.myst} - '13': {name: punctuation.definition.string.myst} - '14': {name: punctuation.definition.string.myst} - '15': {name: punctuation.definition.metadata.myst} - '2': {name: string.other.link.description.myst} - '4': {name: punctuation.definition.string.end.myst} - '5': {name: punctuation.definition.metadata.myst} - '6': {name: punctuation.definition.link.myst} - '7': {name: markup.underline.link.image.myst} - '8': {name: punctuation.definition.link.myst} - '9': {name: string.other.link.description.title.myst} - match: > - (?x) - (\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - (\() # Opening paren for url - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - name: meta.image.inline.myst - image-ref: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '2': {name: string.other.link.description.myst} - '4': {name: punctuation.definition.string.begin.myst} - '5': {name: punctuation.definition.constant.myst} - '6': {name: constant.other.reference.link.myst} - '7': {name: punctuation.definition.constant.myst} - match: (\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) - name: meta.image.reference.myst - italic: - begin: > - (?x) - (?<open>(\*(?=\w)|(?<!\w)\*|(?<!\w)\b_))(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | \k<open>\k<open> # Must be bold closer - | (?!(?<=\S)\k<open>). # Everything besides - # style closer - )++ - (?<=\S)(?=_\b|\*)\k<open> # Close - ) - captures: - '1': {name: punctuation.definition.italic.myst} - end: (?<=\S)(\1)((?!\1)|(?=\1\1)) - name: markup.italic.myst - patterns: - - applyEndPatternLast: 1 - begin: (?=<[^>]*?>) - end: (?<=>) - patterns: - - {include: text.html.derivative} - - {include: '#escape'} - - {include: '#ampersand'} - - {include: '#bracket'} - - {include: '#raw'} - - {include: '#bold'} - - {include: '#image-inline'} - - {include: '#link-inline'} - - {include: '#link-inet'} - - {include: '#link-email'} - - {include: '#image-ref'} - - {include: '#link-ref-literal'} - - {include: '#link-ref'} - - {include: '#link-ref-shortcut'} - link-email: - captures: - '1': {name: punctuation.definition.link.myst} - '2': {name: markup.underline.link.myst} - '4': {name: punctuation.definition.link.myst} - match: (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) - name: meta.link.email.lt-gt.myst - link-inet: - captures: - '1': {name: punctuation.definition.link.myst} - '2': {name: markup.underline.link.myst} - '3': {name: punctuation.definition.link.myst} - match: (<)((?:https?|ftp)://.*?)(>) - name: meta.link.inet.myst - link-inline: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '2': {name: string.other.link.title.myst} - '4': {name: punctuation.definition.string.end.myst} - '5': {name: punctuation.definition.metadata.myst} - '6': {name: punctuation.definition.link.myst} - '7': {name: markup.underline.link.myst} - '9': {name: punctuation.definition.link.myst} - '10': {name: string.other.link.description.title.myst} - '11': {name: punctuation.definition.string.begin.myst} - '12': {name: punctuation.definition.string.end.myst} - '13': {name: string.other.link.description.title.myst} - '14': {name: punctuation.definition.string.begin.myst} - '15': {name: punctuation.definition.string.end.myst} - '16': {name: punctuation.definition.metadata.myst} - match: > - (?x) - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - (\() # Opening paren for url - (<?)((?<url>(?>[^\s()]+)|\(\g<url>*\))*)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - name: meta.link.inline.myst - link-ref: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '2': {name: string.other.link.title.myst} - '4': {name: punctuation.definition.string.end.myst} - '5': {name: punctuation.definition.constant.begin.myst} - '6': {name: constant.other.reference.link.myst} - '7': {name: punctuation.definition.constant.end.myst} - match: (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])(\[)([^\]]*+)(\]) - name: meta.link.reference.myst - link-ref-literal: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '2': {name: string.other.link.title.myst} - '4': {name: punctuation.definition.string.end.myst} - '5': {name: punctuation.definition.constant.begin.myst} - '6': {name: punctuation.definition.constant.end.myst} - match: (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) - name: meta.link.reference.literal.myst - link-ref-shortcut: - captures: - '1': {name: punctuation.definition.string.begin.myst} - '2': {name: string.other.link.title.myst} - '3': {name: punctuation.definition.string.end.myst} - match: (\[)(\S+?)(\]) - name: meta.link.reference.myst - raw: - captures: - '1': {name: punctuation.definition.raw.myst} - '3': {name: punctuation.definition.raw.myst} - match: (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) - name: markup.inline.raw.string.myst - blockquote: - begin: (^|\G)[ ]{0,3}(>) ? - captures: - '2': {name: punctuation.definition.quote.begin.myst} - name: markup.quote.myst - patterns: - - {include: '#block'} - while: (^|\G)\s*(>) ? - directive_block_admonition: - begin: (^|\G)(\s*)(`{3,}|~{3,})\{(attention|caution|danger|error|note|important|tip|hint|warning)\}\s*(?=([^`~]*)?$) - beginCaptures: - '3': {name: punctuation.definition.myst} - '4': {name: support.class.directive.myst} - '5': {name: support.variable.attributes.directive.myst} - end: (^|\G)(\3|\s{0,3})(\4)\s*$ - endCaptures: - '3': {name: punctuation.definition.myst} - patterns: - - begin: (^|\G)(\s*)(.*) - while: (^|\G)(?!\s*([\`~]{3,})\s*$) - contentName: meta.embedded.block.myst - patterns: - - {include: $self} - name: markup.directive_code.block.myst - fenced_code_block_unknown: - begin: (^|\G)(\s*)(`{3,}|~{3,})\s*(?=([^`~]*)?$) - beginCaptures: - '3': {name: punctuation.definition.myst} - '4': {name: fenced_code.block.language} - end: (^|\G)(\2|\s{0,3})(\3)\s*$ - endCaptures: - '3': {name: punctuation.definition.myst} - name: markup.fenced_code.block.myst - directive_block_unknown: - begin: (^|\G)(\s*)(`{3,}|~{3,})\s*\{([a-zA-Z0-9\_\-\@]+)\}\s*(?=([^`~]*)?$) - beginCaptures: - '3': {name: punctuation.definition.myst} - '4': {name: support.class.directive.myst} - '5': {name: 'support.variable.language.myst'} - end: (^|\G)(\2|\s{0,3})(\3)\s*$ - endCaptures: - '3': {name: punctuation.definition.myst} - name: markup.fenced_code.block.myst -{{codeCellDefinitions}} - directive_block: - patterns: - - {include: '#directive_block_admonition'} - {{codeCellIncludes}} - - {include: '#directive_block_unknown'} -{{languageDefinitions}} - fenced_code_block: - patterns: - {{languageIncludes}} - - {include: '#fenced_code_block_unknown'} -scopeName: text.html.myst -uuid: 0A1D9874-B448-11D9-BD50-000D93B6E43D diff --git a/logo/icon_128x128.png b/logo/icon_128x128.png index 0c0a662..e0c4c85 100644 Binary files a/logo/icon_128x128.png and b/logo/icon_128x128.png differ diff --git a/package-lock.json b/package-lock.json index bf09904..c64d928 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,21 @@ "version": "0.10.2", "license": "MIT", "dependencies": { - "@types/markdown-it": "0.0.9", "js-yaml": "^3.13.1", - "markdown-it": "^10.0.0" + "katex": "^0.13.11", + "markdown-it-amsmath": "^0.1.2", + "markdown-it-deflist": "^2.1.0", + "markdown-it-docutils": "^0.0.12", + "markdown-it-dollarmath": "^0.2.0", + "markdown-it-footnote": "^3.0.3", + "markdown-it-front-matter": "^0.2.3", + "markdown-it-task-lists": "^2.1.1" }, "devDependencies": { "@types/glob": "^7.1.1", "@types/js-yaml": "^3.12.2", + "@types/katex": "^0.11.1", + "@types/markdown-it": "^12.0.2", "@types/mocha": "^5.2.6", "@types/node": "^8.10.25", "@types/nunjucks": "^3.1.3", @@ -27,6 +35,7 @@ "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.20.1", "eslint-plugin-prettier": "^3.4.0", + "markdown-it": "^12.1.0", "minimist": ">=1.2.2", "mocha": "^6.1.4", "nunjucks": "^3.2.1", @@ -170,6 +179,12 @@ "@types/node": "*" } }, + "node_modules/@types/highlight.js": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.4.tgz", + "integrity": "sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww==", + "dev": true + }, "node_modules/@types/js-yaml": { "version": "3.12.6", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.6.tgz", @@ -188,19 +203,35 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/katex": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz", + "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==", + "dev": true + }, "node_modules/@types/linkify-it": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.1.tgz", - "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==" + "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==", + "dev": true }, "node_modules/@types/markdown-it": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.9.tgz", - "integrity": "sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.0.2.tgz", + "integrity": "sha512-p4DIfLMmGN0iLSbMxknDXeSm8W2ZRqQeN/1EAwVxVqJietzgp3WeP1UQjCKWDXWBcEbUa1ECx8YAfdpQdDQmZQ==", + "dev": true, "dependencies": { - "@types/linkify-it": "*" + "@types/highlight.js": "^9.7.0", + "@types/linkify-it": "*", + "@types/mdurl": "*" } }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, "node_modules/@types/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", @@ -944,9 +975,12 @@ } }, "node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, "node_modules/error-ex": { "version": "1.3.2", @@ -2144,6 +2178,25 @@ "json5": "lib/cli.js" } }, + "node_modules/katex": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.11.tgz", + "integrity": "sha512-yJBHVIgwlAaapzlbvTpVF/ZOs8UkTj/sd46Fl8+qAf2/UiituPYVeapVD8ADZtqyRg/qNWUKt7gJoyYVWLrcXw==", + "dependencies": { + "commander": "^6.0.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2158,9 +2211,9 @@ } }, "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", "dependencies": { "uc.micro": "^1.0.1" } @@ -2248,13 +2301,13 @@ } }, "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.1.0.tgz", + "integrity": "sha512-7temG6IFOOxfU0SgzhqR+vr2diuMhyO5uUIEZ3C5NbXhqC9uFUHoU41USYuDFoZRsaY7BEIEei874Z20VMLF6A==", "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, @@ -2262,6 +2315,67 @@ "markdown-it": "bin/markdown-it.js" } }, + "node_modules/markdown-it-amsmath": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/markdown-it-amsmath/-/markdown-it-amsmath-0.1.2.tgz", + "integrity": "sha512-iIM7IVjT6HkuEDAiXLWuoAcIkxrk795XkBzRN9jCKyZKWe5doTaUh1ZzevBx56WBpNZnOB+b3Z6H3Lhifd+0wA==", + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/markdown-it-deflist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz", + "integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg==" + }, + "node_modules/markdown-it-docutils": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/markdown-it-docutils/-/markdown-it-docutils-0.0.12.tgz", + "integrity": "sha512-JXRNcBjvBr0iUb2t9bxKXqyT38AOkoQpUZnkcVmLDeoy/4IkB+ik1EpzCQoysbJ4JGM5i7GN/epRn9nrL7gSvg==", + "dependencies": { + "js-yaml": "^3.14.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "markdown-it": "12.x" + } + }, + "node_modules/markdown-it-dollarmath": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-dollarmath/-/markdown-it-dollarmath-0.2.0.tgz", + "integrity": "sha512-1b4sAe+L3MtSviZL9c9jE46KF/96MwqOpLNLLzYB1UAAAjVDsTcHd+mWLZI12toP111WcfEMmpAW1uyZJsPhlw==", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "markdown-it": "12.x" + } + }, + "node_modules/markdown-it-footnote": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", + "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==" + }, + "node_modules/markdown-it-front-matter": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/markdown-it-front-matter/-/markdown-it-front-matter-0.2.3.tgz", + "integrity": "sha512-s9+rcClLmZsZc3YL8Awjg/YO/VdphlE20LJ9Bx5a8RAFLI5a1vq6Mll8kOzG6w/wy8yhFLBupaa6Mfd60GATkA==" + }, + "node_modules/markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -4085,6 +4199,12 @@ "@types/node": "*" } }, + "@types/highlight.js": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.4.tgz", + "integrity": "sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww==", + "dev": true + }, "@types/js-yaml": { "version": "3.12.6", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.6.tgz", @@ -4103,19 +4223,35 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/katex": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz", + "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==", + "dev": true + }, "@types/linkify-it": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.1.tgz", - "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==" + "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==", + "dev": true }, "@types/markdown-it": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.9.tgz", - "integrity": "sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.0.2.tgz", + "integrity": "sha512-p4DIfLMmGN0iLSbMxknDXeSm8W2ZRqQeN/1EAwVxVqJietzgp3WeP1UQjCKWDXWBcEbUa1ECx8YAfdpQdDQmZQ==", + "dev": true, "requires": { - "@types/linkify-it": "*" + "@types/highlight.js": "^9.7.0", + "@types/linkify-it": "*", + "@types/mdurl": "*" } }, + "@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, "@types/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", @@ -4654,9 +4790,9 @@ } }, "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" }, "error-ex": { "version": "1.3.2", @@ -5548,6 +5684,21 @@ "minimist": "^1.2.0" } }, + "katex": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.11.tgz", + "integrity": "sha512-yJBHVIgwlAaapzlbvTpVF/ZOs8UkTj/sd46Fl8+qAf2/UiituPYVeapVD8ADZtqyRg/qNWUKt7gJoyYVWLrcXw==", + "requires": { + "commander": "^6.0.0" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" + } + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5559,9 +5710,9 @@ } }, "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", "requires": { "uc.micro": "^1.0.1" } @@ -5637,17 +5788,63 @@ } }, "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.1.0.tgz", + "integrity": "sha512-7temG6IFOOxfU0SgzhqR+vr2diuMhyO5uUIEZ3C5NbXhqC9uFUHoU41USYuDFoZRsaY7BEIEei874Z20VMLF6A==", "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } + } + }, + "markdown-it-amsmath": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/markdown-it-amsmath/-/markdown-it-amsmath-0.1.2.tgz", + "integrity": "sha512-iIM7IVjT6HkuEDAiXLWuoAcIkxrk795XkBzRN9jCKyZKWe5doTaUh1ZzevBx56WBpNZnOB+b3Z6H3Lhifd+0wA==" + }, + "markdown-it-deflist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz", + "integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg==" + }, + "markdown-it-docutils": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/markdown-it-docutils/-/markdown-it-docutils-0.0.12.tgz", + "integrity": "sha512-JXRNcBjvBr0iUb2t9bxKXqyT38AOkoQpUZnkcVmLDeoy/4IkB+ik1EpzCQoysbJ4JGM5i7GN/epRn9nrL7gSvg==", + "requires": { + "js-yaml": "^3.14.1" } }, + "markdown-it-dollarmath": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-dollarmath/-/markdown-it-dollarmath-0.2.0.tgz", + "integrity": "sha512-1b4sAe+L3MtSviZL9c9jE46KF/96MwqOpLNLLzYB1UAAAjVDsTcHd+mWLZI12toP111WcfEMmpAW1uyZJsPhlw==", + "requires": {} + }, + "markdown-it-footnote": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", + "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==" + }, + "markdown-it-front-matter": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/markdown-it-front-matter/-/markdown-it-front-matter-0.2.3.tgz", + "integrity": "sha512-s9+rcClLmZsZc3YL8Awjg/YO/VdphlE20LJ9Bx5a8RAFLI5a1vq6Mll8kOzG6w/wy8yhFLBupaa6Mfd60GATkA==" + }, + "markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" + }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -6047,7 +6244,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^2.0.0" + "pify": "^3.0.0" } }, "picomatch": { diff --git a/package.json b/package.json index dc1621e..c45aa67 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,6 @@ "displayName": "MyST-Markdown", "description": "The official Markdown syntax extension for MyST (Markedly Structured Text)", "version": "0.10.2", - "repository": { - "type": "git", - "url": "https://github.com/ExecutableBookProject/myst-highlight-grammar.git" - }, - "homepage": "https://github.com/ExecutableBookProject/myst-highlight-grammar/blob/master/README.md", "publisher": "ExecutableBookProject", "keywords": [ "markdown", @@ -17,13 +12,78 @@ "Chris Sewell" ], "license": "MIT", - "engines": { - "vscode": "^1.41.0" + "repository": { + "type": "git", + "url": "https://github.com/ExecutableBookProject/myst-language-support.git" + }, + "homepage": "https://github.com/ExecutableBookProject/myst-language-support/blob/master/README.md", + "bugs": { + "url": "https://github.com/ExecutableBookProject/myst-language-support/issues/new/choose" }, "categories": [ "Programming Languages" ], "icon": "logo/icon_128x128.png", + "engines": { + "vscode": "^1.41.0" + }, + "main": "out/extension", + "dependencies": { + "js-yaml": "^3.13.1", + "katex": "^0.13.11", + "markdown-it-amsmath": "^0.1.2", + "markdown-it-deflist": "^2.1.0", + "markdown-it-docutils": "^0.0.12", + "markdown-it-dollarmath": "^0.2.0", + "markdown-it-footnote": "^3.0.3", + "markdown-it-front-matter": "^0.2.3", + "markdown-it-task-lists": "^2.1.1" + }, + "devDependencies": { + "@types/glob": "^7.1.1", + "@types/js-yaml": "^3.12.2", + "@types/katex": "^0.11.1", + "@types/markdown-it": "^12.0.2", + "@types/mocha": "^5.2.6", + "@types/node": "^8.10.25", + "@types/nunjucks": "^3.1.3", + "@types/plist": "^3.0.2", + "@types/vscode": "^1.41.0", + "@typescript-eslint/eslint-plugin": "^4.28.2", + "@typescript-eslint/parser": "^4.28.2", + "eslint": "^7.30.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-prettier": "^3.4.0", + "markdown-it": "^12.1.0", + "minimist": ">=1.2.2", + "mocha": "^6.1.4", + "nunjucks": "^3.2.1", + "plist": "^3.0.1", + "prettier": "^2.3.2", + "process": "^0.11.10", + "tslint": "^5.8.0", + "typescript": "^3.5.1", + "vscode-test": "^1.3.0" + }, + "scripts": { + "format": "prettier --write src/*.ts src/**/*.ts", + "lint": "eslint -c .eslintrc.yaml --max-warnings 1 --cache --ext .ts,.js .", + "lint:fix": "eslint -c .eslintrc.yaml --fix --cache --ext .ts,.js .", + "vscode:prepublish": "npm run build", + "build:code": "tsc -p ./", + "build:assets": "node out/build", + "build": "npm run build:code && npm run build:assets", + "watch": "tsc -watch -p ./", + "pretest": "npm run build", + "test:unit": "mocha --ui tdd out/test/standalone/", + "test:integration": "node out/test/runIntergration.js", + "test": "npm run test:unit && npm run test:integration" + }, + "activationEvents": [ + "onCommand:myst.Activate", + "onLanguage:markdown" + ], "contributes": { "grammars": [ { @@ -51,6 +111,9 @@ } ], "markdown.markdownItPlugins": true, + "markdown.previewStyles": [ + "./node_modules/markdown-it-docutils/dist/css/style.min.css" + ], "configuration": { "title": "MyST-Markdown Configuration", "properties": { @@ -58,56 +121,25 @@ "description": "Whether to enable the Markdown Preview extension (requires reload)", "type": "boolean", "default": true + }, + "myst.preview.extensions": { + "description": "The syntax extensions to load", + "type": "array", + "items": { + "type": "string", + "enum": [ + "amsmath", + "colon_fence", + "deflist", + "dollarmath", + "tasklist" + ] + }, + "default": [ + "dollarmath" + ] } } } - }, - "main": "out/extension", - "activationEvents": [ - "onCommand:myst.Activate", - "onLanguage:markdown" - ], - "bugs": { - "url": "https://github.com/ExecutableBookProject/myst-highlight-grammar/issues/new/choose" - }, - "devDependencies": { - "@types/glob": "^7.1.1", - "@types/js-yaml": "^3.12.2", - "@types/mocha": "^5.2.6", - "@types/node": "^8.10.25", - "@types/nunjucks": "^3.1.3", - "@types/plist": "^3.0.2", - "@types/vscode": "^1.41.0", - "@typescript-eslint/eslint-plugin": "^4.28.2", - "@typescript-eslint/parser": "^4.28.2", - "eslint": "^7.30.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.20.1", - "eslint-plugin-prettier": "^3.4.0", - "minimist": ">=1.2.2", - "mocha": "^6.1.4", - "nunjucks": "^3.2.1", - "plist": "^3.0.1", - "prettier": "^2.3.2", - "process": "^0.11.10", - "tslint": "^5.8.0", - "typescript": "^3.5.1", - "vscode-test": "^1.3.0" - }, - "dependencies": { - "@types/markdown-it": "0.0.9", - "js-yaml": "^3.13.1", - "markdown-it": "^10.0.0" - }, - "scripts": { - "format": "prettier --write src/*.ts src/**/*.ts", - "lint": "eslint -c .eslintrc.yaml --max-warnings 1 --cache --ext .ts,.js .", - "lint:fix": "eslint -c .eslintrc.yaml --fix --cache --ext .ts,.js .", - "build": "node out/build", - "vscode:prepublish": "npm run compile && npm run build", - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", - "pretest": "npm run compile && npm run build", - "test": "node out/test/runIntergration.js && mocha --ui tdd out/test/standalone/" } } diff --git a/src/directives.ts b/src/directivesCompletion.ts similarity index 72% rename from src/directives.ts rename to src/directivesCompletion.ts index 718db13..e0d2361 100644 --- a/src/directives.ts +++ b/src/directivesCompletion.ts @@ -3,10 +3,10 @@ import * as vscode from "vscode" import * as yaml from "js-yaml" import * as dirDict from "./data/directives.json" -const dirRegexp = new RegExp(".*[`]{3,}\\{") // TODO check not backslash escapes +const dirRegexp = new RegExp(".*[`:]{3,}\\{") // TODO check not backslash escapes const dirStartRegexp = new RegExp("\\{[a-zA-Z0-9\\-]+\\}") -export function getDirectiveData(name: string) { +export function getDirectiveData(name: string): any { const dict: { [key: string]: any } = dirDict return dict[name] } @@ -27,7 +27,11 @@ export class CompletionItemProvider implements vscode.CompletionItemProvider { const completions: vscode.CompletionItem[] = [] const dict: { [key: string]: any } = dirDict for (const name in dirDict) { - directiveCompletion(name, dict[name], completions) + try { + directiveCompletion(name, dict[name], completions) + } catch (error) { + console.warn(`Could not create directive completion: ${name}: ${error}`) + } } return completions } @@ -35,7 +39,7 @@ export class CompletionItemProvider implements vscode.CompletionItemProvider { } } -export function makeDescription(data: any, addClass: boolean = false) { +export function makeDescription(data: any, addClass = false): vscode.MarkdownString { const opts = yaml.safeDump({ "Required Args": data["required_arguments"], "Optional Args": data["optional_arguments"], @@ -44,9 +48,9 @@ export function makeDescription(data: any, addClass: boolean = false) { }) let string = "" if (addClass) { - string = "`" + data["klass"] + "`\n\n" + string = "`" + `${data["klass"]}` + "`\n\n" } - string = string + data["description"] + string = string + `${data["description"]}` const mdown = new vscode.MarkdownString(string) mdown.appendCodeblock(opts, "yaml") return mdown @@ -72,18 +76,24 @@ export class HoverProvider implements vscode.HoverProvider { ): Promise<vscode.Hover> { const range = document.getWordRangeAtPosition(position, dirStartRegexp) if (range === undefined) { - return new Promise(resolve => resolve()) + return new Promise(resolve => + resolve(new vscode.Hover(new vscode.MarkdownString(""))) + ) } const textLine = document.lineAt(range.start) const startLine = textLine.text.slice(undefined, range.start.character) - if (!startLine.endsWith("```")) { - return new Promise(resolve => resolve()) + if (!(startLine.endsWith("```") || startLine.endsWith(":::"))) { + return new Promise(resolve => + resolve(new vscode.Hover(new vscode.MarkdownString(""))) + ) } // TODO check for backslash escapes let text = document.getText(range) text = text.slice(1, -1) if (!(text in dirDict)) { - return new Promise(resolve => resolve()) + return new Promise(resolve => + resolve(new vscode.Hover(new vscode.MarkdownString(""))) + ) } const data = getDirectiveData(text) const mkdown = makeDescription(data, true) diff --git a/src/extension.ts b/src/extension.ts index 8a36c94..ecae783 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,8 +2,19 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from "vscode" -import { CompletionItemProvider, HoverProvider } from "./directives" -import { markitPlugin } from "./md_it_plugin" +import { CompletionItemProvider, HoverProvider } from "./directivesCompletion" +import frontMatterPlugin from "markdown-it-front-matter" +import footnotePlugin from "markdown-it-footnote" +import docutilsPlugin from "markdown-it-docutils" +import type MarkdownIt from "markdown-it" +import dollarmathPlugin from "markdown-it-dollarmath" +import amsmathPlugin from "markdown-it-amsmath" +import deflistPlugin from "markdown-it-deflist" +import tasklistPlugin from "markdown-it-task-lists" +import { renderToString } from "katex" +import { colonFencePlugin, convertFrontMatter, mystBlockPlugin } from "./mdPlugins" + +const extensionId = "executablebookproject.myst-highlight" // this method is called when your extension is activated // your extension is activated the very first time the command is executed @@ -13,14 +24,16 @@ export function activate(context: vscode.ExtensionContext) { console.log("Activated MyST-Markdown extension") // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand + // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json const disposable = vscode.commands.registerCommand("myst.Activate", () => { // The code you place here will be executed every time your command is executed // Display a message box to the user - vscode.window.showInformationMessage("Activated MyST-Markdown!") + void vscode.window.showInformationMessage("Activated MyST-Markdown!") }) + notifyNewReleases(context) + context.subscriptions.push(disposable) const mdSelector: vscode.DocumentSelector = { scheme: "file", language: "markdown" } @@ -40,11 +53,84 @@ export function activate(context: vscode.ExtensionContext) { return {} } return { - extendMarkdownIt(md: any) { - return md.use(markitPlugin) + extendMarkdownIt(md: MarkdownIt) { + // note ideally here, we would want to specify the config as commonmark, rather than default + const extensions: string[] = vscode.workspace + .getConfiguration("myst.preview") + .get("extensions", []) + let newMd = md + .enable("table") + .use(frontMatterPlugin, () => {}) + .use(convertFrontMatter) + .use(mystBlockPlugin) + .use(footnotePlugin) + .disable("footnote_inline") // not yet implemented in myst-parser + .use(docutilsPlugin) + + if (extensions.includes("dollarmath")) { + newMd = newMd.use(dollarmathPlugin, { + double_inline: true, + renderer: renderToString, + optionsInline: { throwOnError: false, displayMode: false }, + optionsBlock: { throwOnError: false, displayMode: true } + }) + } + if (extensions.includes("colon_fence")) { + newMd = newMd.use(colonFencePlugin) + } + if (extensions.includes("amsmath")) { + newMd = newMd.use(amsmathPlugin, { + renderer: renderToString, + options: { throwOnError: false, displayMode: true } + }) + } + if (extensions.includes("deflist")) { + newMd = newMd.use(deflistPlugin) + } + if (extensions.includes("tasklist")) { + newMd = newMd.use(tasklistPlugin) + } + // TODO substitutions + return newMd } } } // this method is called when your extension is deactivated export function deactivate() {} + +/** Notify users that if the extension has been updated to a new major release */ +function notifyNewReleases(context: vscode.ExtensionContext) { + const previousVersion = context.globalState.get("previousVersion") + const currentVersion = + vscode.extensions.getExtension(extensionId)?.packageJSON.version + void context.globalState.update("previousVersion", currentVersion) + if (typeof previousVersion !== "string") { + console.log(`set previousVersion: ${currentVersion}`) + return + } + if (typeof currentVersion === "string" && currentVersion !== previousVersion) { + if (isMajorUpdate(previousVersion, currentVersion)) { + void vscode.window.showInformationMessage( + `MyST-Markdown updated to v${currentVersion}. See the Changelog for what's new!` + ) + } + } +} + +/** Check if major update to extension or, if major version is 0, check patch version */ +function isMajorUpdate(previousVersion: string, currentVersion: string): boolean { + try { + const previousVerArr = previousVersion.split(".").map(Number) + const currentVerArr = currentVersion.split(".").map(Number) + if (currentVerArr[0] === 0 && currentVerArr[1] > previousVerArr[1]) { + return true + } + if (currentVerArr[0] > previousVerArr[0]) { + return true + } + } catch (error) { + console.warn(`Failed to read extension versions: ${error}`) + } + return false +} diff --git a/src/mdPlugins.ts b/src/mdPlugins.ts new file mode 100644 index 0000000..ff4140e --- /dev/null +++ b/src/mdPlugins.ts @@ -0,0 +1,313 @@ +/** Local markdown-it plugins */ +import type MarkdownIt from "markdown-it" +import type StateBlock from "markdown-it/lib/rules_block/state_block" +import type StateCore from "markdown-it/lib/rules_core/state_core" +import type Token from "markdown-it/lib/token" + +/** Markdown-it plugin to convert the front-matter token to a renderable token, for previews */ +export function convertFrontMatter(md: MarkdownIt) { + md.core.ruler.after("block", "convert_front_matter", (state: StateCore) => { + if (state.tokens.length && state.tokens[0].type === "front_matter") { + const replace = new state.Token("fence", "code", 0) + replace.map = state.tokens[0].map + replace.info = "yaml" + replace.content = state.tokens[0].meta + state.tokens[0] = replace + } + return true + }) +} + +/** Parse MyST targets (``(name)=``), blockquotes (``% comment``) and block breaks (``+++``). + * + * Adapted from: mdit_py_plugins/myst_blocks/index.py + */ +export function mystBlockPlugin(md: MarkdownIt): void { + md.block.ruler.before("blockquote", "myst_line_comment", parse_line_comment, { + alt: ["paragraph", "reference", "blockquote", "list", "footnote_def"] + }) + md.block.ruler.before("hr", "myst_block_break", parse_block_break, { + alt: ["paragraph", "reference", "blockquote", "list", "footnote_def"] + }) + md.block.ruler.before("hr", "myst_target", parse_target, { + alt: ["paragraph", "reference", "blockquote", "list", "footnote_def"] + }) + md.renderer.rules.myst_line_comment = render_myst_line_comment + md.renderer.rules.myst_target = render_myst_target +} + +function parse_line_comment( + state: StateBlock, + startLine: number, + endLine: number, + silent: boolean +): boolean { + let pos = state.bMarks[startLine] + state.tShift[startLine] + let maximum = state.eMarks[startLine] + + // if it's indented more than 3 spaces, it should be a code block + if (state.sCount[startLine] - state.blkIndent >= 4) { + return false + } + + if (state.src[pos] !== "%") { + return false + } + + if (silent) { + return true + } + + const token = state.push("myst_line_comment", "", 0) + token.attrSet("class", "myst-line-comment") + token.content = state.src.slice(pos + 1, maximum).replace(/\s+$/gm, "") // rstrip + token.markup = "%" + + // search end of block while appending lines to `token.content` + let nextLine: number + for (nextLine = startLine + 1; nextLine < endLine; nextLine++) { + pos = state.bMarks[nextLine] + state.tShift[nextLine] + maximum = state.eMarks[nextLine] + if (state.src[pos] !== "%") { + break + } + token.content += "\n" + state.src.slice(pos + 1, maximum).replace(/\s+$/gm, "") // rstrip + } + state.line = nextLine + token.map = [startLine, nextLine] + + return true +} + +function parse_block_break( + state: StateBlock, + startLine: number, + endLine: number, + silent: boolean +): boolean { + let pos = state.bMarks[startLine] + state.tShift[startLine] + const maximum = state.eMarks[startLine] + + // if it's indented more than 3 spaces, it should be a code block + if (state.sCount[startLine] - state.blkIndent >= 4) { + return false + } + + const marker = state.src.charCodeAt(pos) + pos += 1 + + // Check block marker /* + */ + if (marker !== 0x2b) { + return false + } + + // markers can be mixed with spaces, but there should be at least 3 of them + + let cnt = 1 + while (pos < maximum) { + const ch = state.src.charCodeAt(pos) + if (ch !== marker && !state.md.utils.isSpace(ch)) { + break + } + if (ch === marker) { + cnt += 1 + } + pos += 1 + } + + if (cnt < 3) { + return false + } + + if (silent) { + return true + } + + state.line = startLine + 1 + + const token = state.push("myst_block_break", "hr", 0) + token.attrSet("class", "myst-block") + token.content = state.src.slice(pos, maximum).trim() + token.map = [startLine, state.line] + token.markup = state.md.utils.fromCodePoint(marker).repeat(cnt) + + return true +} + +const TARGET_PATTERN = /^\((?<label>[a-zA-Z0-9|@<>*./_\-+:]{1,100})\)=\s*$/ + +function parse_target( + state: StateBlock, + startLine: number, + endLine: number, + silent: boolean +): boolean { + const pos = state.bMarks[startLine] + state.tShift[startLine] + const maximum = state.eMarks[startLine] + + // if it's indented more than 3 spaces, it should be a code block + if (state.sCount[startLine] - state.blkIndent >= 4) { + return false + } + const match = TARGET_PATTERN.exec(state.src.slice(pos, maximum)) + if (!match) { + return false + } + if (silent) { + return true + } + + state.line = startLine + 1 + + const token = state.push("myst_target", "", 0) + token.attrSet("class", "myst-target") + token.content = match && match.groups ? match.groups["label"] : "" + token.map = [startLine, state.line] + + return true +} + +function escapeHtml(unsafe: string) { + return unsafe + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") +} + +function render_myst_line_comment(tokens: Token[], idx: number): string { + const token = tokens[idx] + const content = token.content + return `<!-- ${escapeHtml(content).trim()} -->` +} + +function render_myst_target(tokens: Token[], idx: number) { + const token = tokens[idx] + const className = "myst-target" + const label = token.content + const target = `<a href="#${label}">(${label})=</a>` + return `<div class="${className}">${target}</div>` +} + +/** Colon fence + * This plugin directly mimics regular fences, but with `:` colons. + * + * Example: + + :::name + contained text + ::: + * +*/ +export function colonFencePlugin(md: MarkdownIt): void { + md.block.ruler.before("fence", "colon_fence", colon_fence_rule, { + alt: ["paragraph", "reference", "blockquote", "list", "footnote_def"] + }) +} + +function colon_fence_rule( + state: StateBlock, + startLine: number, + endLine: number, + silent: boolean +): boolean { + let haveEndMarker = false + let pos = state.bMarks[startLine] + state.tShift[startLine] + let max = state.eMarks[startLine] + + // if it's indented more than 3 spaces, it should be a code block + if (state.sCount[startLine] - state.blkIndent >= 4) { + return false + } + + if (pos + 3 > max) { + return false + } + + const marker = state.src.charCodeAt(pos) + + if (marker !== 0x3a /* : */) { + return false + } + + // scan marker length + let mem = pos + pos = state.skipChars(pos, marker) + + let len = pos - mem + + if (len < 3) { + return false + } + + const markup = state.src.slice(mem, pos) + const params = state.src.slice(pos, max) + + // Since start is found, we can report success here in validation mode + if (silent) { + return true + } + + // search end of block + let nextLine = startLine + + for (;;) { + nextLine++ + if (nextLine >= endLine) { + // unclosed block should be autoclosed by end of document. + // also block seems to be autoclosed by end of parent + break + } + + pos = mem = state.bMarks[nextLine] + state.tShift[nextLine] + max = state.eMarks[nextLine] + + if (pos < max && state.sCount[nextLine] < state.blkIndent) { + // non-empty line with negative indent should stop the list: + // - ``` + // test + break + } + + if (state.src.charCodeAt(pos) !== marker) { + continue + } + + if (state.sCount[nextLine] - state.blkIndent >= 4) { + // closing fence should be indented less than 4 spaces + continue + } + + pos = state.skipChars(pos, marker) + + // closing code fence must be at least as long as the opening one + if (pos - mem < len) { + continue + } + + // make sure tail has spaces only + pos = state.skipSpaces(pos) + + if (pos < max) { + continue + } + + haveEndMarker = true + // found! + break + } + + // If a fence has heading spaces, they should be removed from its inner block + len = state.sCount[startLine] + + state.line = nextLine + (haveEndMarker ? 1 : 0) + + const token = state.push("fence", "code", 0) + token.info = params + token.content = state.getLines(startLine + 1, nextLine, len, true) + token.markup = markup + token.map = [startLine, state.line] + + return true +} diff --git a/src/md_it_plugin.ts b/src/md_it_plugin.ts deleted file mode 100644 index 6a8b842..0000000 --- a/src/md_it_plugin.ts +++ /dev/null @@ -1,128 +0,0 @@ -import * as MarkdownIt from "markdown-it" -import { Rule } from "markdown-it" -import Token = require("markdown-it/lib/token") // eslint-disable-line - -/** - * Create a block tokenizer function, with an instantiated MarkdownIt instance - */ -export function makeToTokens(md: MarkdownIt, env: any = {}) { - function toTokens(input: string, startLine: number | null = null) { - const tokens: Token[] = [] - // TODO I think ideally we would use md.block.tokenize, to directly set startLine - // however, it is not specified on the type - // for possible fix: https://github.com/Microsoft/TypeScript/issues/2076 - md.block.parse(input, md, env, tokens) - if (startLine !== null) { - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index] - if (token.map !== null) { - token.map = [token.map[0] + startLine, token.map[1] + startLine] - } - } - } - return tokens - } - return toTokens -} - -/** - * make open/close tokens for an admonition - * @param original the fenced code block that is being expanded - * @param name the name of the directive - * @param attributes the sting after the directive declaration - */ -function makeEnclosure(original: Token, name: string, attributes: string) { - const openToken = new Token("admonition_open", "div", original.nesting) - const dirType = "admonitions" - openToken.meta = { name, attributes, dirType } - openToken.attrSet("class", `admonition ${name}`) - openToken.map = original.map - openToken.info = original.info - openToken.block = true - const closeToken = new Token("admonition_close", "/div", original.nesting) - closeToken.meta = { name, attributes } - closeToken.block = true - return { openToken, closeToken } -} - -/** - * Find fenced code blocks that relate to admonitions and expand them - * @param tokens the list of block tokens - * @param regex the regex to match the string after the triple tick, shoud match groups (name, attributes) - * @param toTokens the function for running nested parses - */ -export function expandAdmonitions(tokens: Token[], regex: RegExp, toTokens: Function) { - let changed = true - while (changed) { - changed = false - const newTokens: Token[] = [] - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index] - const match = token.info.match(regex) - if (token.type === "fence" && match !== null) { - changed = true - // TODO extract inital yaml block (if present) - const nestedTokens = toTokens(token.content, token.map[0]) - const { openToken, closeToken } = makeEnclosure(token, match[1], match[2]) - newTokens.push(openToken) - newTokens.push(...nestedTokens) - newTokens.push(closeToken) - } else { - newTokens.push(token) - } - } - tokens = newTokens - } - return tokens -} - -/** - * Find fenced code blocks that relate to code directives and 'fix' their language - * @param tokens the list of block tokens - * @param regex the regex to match the string after the triple tick, should match groups (name, attributes) - * @param toTokens the function for running nested parses - */ -export function fixCodeCells(tokens: Token[], regex: RegExp) { - const newTokens: Token[] = [] - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index] - const match = token.info.match(regex) - if (token.type === "fence" && match !== null) { - const name = match[1] - // TODO could have aliases, like ipython3 -> ipython - const attributes = match[2] - const dirType = "code" - token.meta = { name, attributes, dirType } - token.attrSet("class", `directive-${name}`) - token.info = attributes - // TODO extract inital yaml block (if present) - // TODO wrap in div (for CSS access)? - newTokens.push(token) - } else { - newTokens.push(token) - } - } - return tokens -} - -export function markitPlugin(md: MarkdownIt) { - // can we initialise/access vscode configuration from here? - - /// this plugin expands nested admonitions - const ruleAdmonitions: Rule = state => { - const toTokens = makeToTokens(md, state.env) - // TODO make the admonitions variable - state.tokens = expandAdmonitions( - state.tokens, - /^\{(attention|caution|danger|error|important|hint|note|seealso|tip|warning)\}\s*(.*)/, - toTokens - ) - } - /// this plugin fixes the language of code directives - const ruleCodeCells: Rule = state => { - // TODO make the directive names variable - state.tokens = fixCodeCells(state.tokens, /^\{(code|code-block|code-cell)\}\s*(.*)/) - } - md.core.ruler.after("block", "expandAdmonitions", ruleAdmonitions) - md.core.ruler.after("block", "fixCodeCells", ruleCodeCells) -} diff --git a/src/readTemplates.ts b/src/readTemplates.ts index 477e2bb..b459166 100644 --- a/src/readTemplates.ts +++ b/src/readTemplates.ts @@ -4,7 +4,7 @@ import * as yaml from "js-yaml" import * as jinja from "nunjucks" import * as plist from "plist" -export function readGrammar(asPlist: boolean = false) { +export function readGrammar(asPlist = false) { const templateYaml = fs.readFileSync( path.join(__dirname, "../template/myst.tmLanguage.j2.yaml"), "utf8" @@ -40,12 +40,14 @@ export function readGrammar(asPlist: boolean = false) { function getDefault(obj: any, name: any, defaultValue: any = null) { const value = obj[name] if (value === undefined) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return defaultValue } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return value } -export function readSnippets(asJson: boolean = false) { +export function readSnippets(asJson = false) { const snippetsYaml = fs.readFileSync( path.join(__dirname, "../snippets/dir.template.yaml"), "utf8" diff --git a/src/test/integration/colorization.test.ts b/src/test/integration/colorization.test.ts index 0279599..c7f2a02 100644 --- a/src/test/integration/colorization.test.ts +++ b/src/test/integration/colorization.test.ts @@ -75,7 +75,10 @@ function hasThemeChange(d: { [key: string]: any }, p: { [key: string]: any }) { suite("colorization", () => { before(() => { // ensure the extension is activated, so the grammar is injected - commands.executeCommand("myst.Activate").then((_data: any) => {}) + commands.executeCommand("myst.Activate").then( + (_data: any) => {}, + () => {} + ) }) // We place the test files in this lower level FoldingRange, so that when this file is compiled to out/test/, @@ -90,6 +93,7 @@ suite("colorization", () => { fixturesFiles.forEach(fixturesFile => { // define a test for each fixture test(fixturesFile, done => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises assertUnchangedTokens(join(extensionColorizeFixturePath, fixturesFile), done) }) }) diff --git a/src/test/integration/extension.test.ts b/src/test/integration/extension.test.ts index f23f759..ffd79e8 100644 --- a/src/test/integration/extension.test.ts +++ b/src/test/integration/extension.test.ts @@ -2,7 +2,7 @@ import * as assert from "assert" import * as vscode from "vscode" -import * as completion from "../../directives" +import * as completion from "../../directivesCompletion" suite("Completions Tests", () => { test("Make description", () => { diff --git a/src/test/integration/index.ts b/src/test/integration/index.ts index 993db80..e4d5993 100644 --- a/src/test/integration/index.ts +++ b/src/test/integration/index.ts @@ -1,6 +1,6 @@ import * as path from "path" -import * as Mocha from "mocha" -import * as glob from "glob" +import Mocha from "mocha" +import glob from "glob" export function run(): Promise<void> { // Create the mocha test diff --git a/src/test/runIntergration.ts b/src/test/runIntergration.ts index 5452e6e..3a95de6 100644 --- a/src/test/runIntergration.ts +++ b/src/test/runIntergration.ts @@ -13,7 +13,7 @@ async function main() { const extensionTestsPath = path.resolve(__dirname, "./integration/index") // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath, version: "1.47.0" }) + await runTests({ extensionDevelopmentPath, extensionTestsPath, version: "1.58.0" }) } catch (err) { console.error(err) console.error("Failed to run tests") @@ -21,4 +21,4 @@ async function main() { } } -main() +void main() diff --git a/src/test/standalone/md_plugin.test.ts b/src/test/standalone/md_plugin.test.ts deleted file mode 100644 index e39e245..0000000 --- a/src/test/standalone/md_plugin.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -"use strict" -import * as assert from "assert" -import { makeToTokens, expandAdmonitions, fixCodeCells } from "../../md_it_plugin" -import * as MarkdownIt from "markdown-it" - -suite("Parse Tests", () => { - test("Parse tokens", () => { - const toTokens = makeToTokens(new MarkdownIt()) - const tokens = toTokens("```{code} dsf\ncontent\n```") - assert.equal(tokens.length, 1) - }) - - test("Expand admonitions", () => { - const toTokens = makeToTokens(new MarkdownIt()) - let tokens = toTokens( - "`````{note}\n\n\n````{tip}\n```python\ncontent\n```\na\n````\nb\n`````" - ) - tokens = expandAdmonitions(tokens, /^\{(note|tip)\}\s*(.*)/, toTokens) - const types = tokens.map(t => t.type) - assert.deepEqual(types, [ - "admonition_open", - "admonition_open", - "fence", - "paragraph_open", - "inline", - "paragraph_close", - "admonition_close", - "paragraph_open", - "inline", - "paragraph_close", - "admonition_close" - ]) - const positions = tokens.map(t => t.map) - assert.deepEqual(positions, [ - [0, 11], - [2, 8], - [2, 5], - [5, 6], - [5, 6], - null, - null, - [8, 9], - [8, 9], - null, - null - ]) - }) - - test("fix Code Cell language", () => { - const toTokens = makeToTokens(new MarkdownIt()) - let tokens = toTokens("```{code} python\ncontent\n```") - tokens = fixCodeCells(tokens, /^\{(code)\}\s*(.*)/) - assert.equal(tokens.length, 1) - assert.equal(tokens[0].info, "python") - }) -}) diff --git a/src/test/standalone/syntax.test.ts b/src/test/standalone/syntax.test.ts new file mode 100644 index 0000000..1c72fc5 --- /dev/null +++ b/src/test/standalone/syntax.test.ts @@ -0,0 +1,44 @@ +"use strict" +import * as assert from "assert" +import * as fs from "fs" +import MarkdownIt from "markdown-it" +import * as path from "path" +import { colonFencePlugin, mystBlockPlugin } from "../../mdPlugins" + +suite("Syntax Fixtures: MyST Blocks", () => { + const fixtures = fs + .readFileSync( + path.join(__dirname, "../../../test_static/syntax-fixtures", "myst_block.md"), + "utf8" + ) + .replace(/\r\n|\n\r|\n|\r/g, "\n") + const mdit = MarkdownIt("commonmark").use(mystBlockPlugin) + fixtures + .split(/\n\.\n\n/) + .map(s => s.split(/\n\.\n/)) + .forEach(([name, text, expected]) => { + test(name, () => { + const rendered = mdit.render(text) + assert.equal(rendered.trim(), expected.trim()) + }) + }) +}) + +suite("Syntax Fixtures: Colon Fence", () => { + const fixtures = fs + .readFileSync( + path.join(__dirname, "../../../test_static/syntax-fixtures", "colon_fence.md"), + "utf8" + ) + .replace(/\r\n|\n\r|\n|\r/g, "\n") + const mdit = MarkdownIt("commonmark").use(colonFencePlugin) + fixtures + .split(/\n\.\n\n/) + .map(s => s.split(/\n\.\n/)) + .forEach(([name, text, expected]) => { + test(name, () => { + const rendered = mdit.render(text) + assert.equal(rendered.trim(), expected.trim()) + }) + }) +}) diff --git a/test_static/colorize-results/directive_code_block_myst.md.json b/test_static/colorize-results/directive_code_block_myst.md.json index e7cc0ed..e35ca8d 100644 --- a/test_static/colorize-results/directive_code_block_myst.md.json +++ b/test_static/colorize-results/directive_code_block_myst.md.json @@ -309,13 +309,13 @@ }, { "c": "console", - "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.class.console.js", + "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js variable.other.object.js", "r": { - "dark_plus": "support.class: #4EC9B0", - "light_plus": "support.class: #267F99", + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.class: #4EC9B0" + "hc_black": "variable: #9CDCFE" } }, { @@ -331,13 +331,13 @@ }, { "c": "log", - "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.function.console.js", + "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js entity.name.function.js", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { @@ -672,13 +672,13 @@ }, { "c": "console", - "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.class.console.js", + "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js variable.other.object.js", "r": { - "dark_plus": "support.class: #4EC9B0", - "light_plus": "support.class: #267F99", + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.class: #4EC9B0" + "hc_black": "variable: #9CDCFE" } }, { @@ -694,13 +694,13 @@ }, { "c": "log", - "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.function.console.js", + "t": "text.html.markdown markup.directive.code.myst meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js entity.name.function.js", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { diff --git a/test_static/colorize-results/issue-42_myst.md.json b/test_static/colorize-results/issue-42_myst.md.json index 9655e25..add3f52 100644 --- a/test_static/colorize-results/issue-42_myst.md.json +++ b/test_static/colorize-results/issue-42_myst.md.json @@ -550,7 +550,7 @@ } }, { - "c": " counts", + "c": " counts: ", "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift", "r": { "dark_plus": "meta.embedded: #D4D4D4", @@ -561,18 +561,18 @@ } }, { - "c": ":", - "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift keyword.operator.ternary.swift", + "c": "[", + "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift punctuation.section.collection-type.begin.swift", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" } }, { - "c": " [S.", + "c": "S.", "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift", "r": { "dark_plus": "meta.embedded: #D4D4D4", @@ -595,13 +595,13 @@ }, { "c": ":", - "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift keyword.operator.ternary.swift", + "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift punctuation.separator.key-value.swift", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -627,7 +627,18 @@ } }, { - "c": "] ", + "c": "]", + "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift punctuation.section.collection-type.end.swift", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": " ", "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.swift", "r": { "dark_plus": "meta.embedded: #D4D4D4", diff --git a/test_static/colorize-results/issue-62-2_myst.md.json b/test_static/colorize-results/issue-62-2_myst.md.json index 0c95db7..93379cb 100644 --- a/test_static/colorize-results/issue-62-2_myst.md.json +++ b/test_static/colorize-results/issue-62-2_myst.md.json @@ -287,13 +287,13 @@ }, { "c": "console", - "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.class.console.js", + "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js variable.other.object.js", "r": { - "dark_plus": "support.class: #4EC9B0", - "light_plus": "support.class: #267F99", + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.class: #4EC9B0" + "hc_black": "variable: #9CDCFE" } }, { @@ -309,13 +309,13 @@ }, { "c": "log", - "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js support.function.console.js", + "t": "text.html.markdown markup.fenced_code.block.markdown meta.embedded.block.javascript meta.function.js meta.block.js meta.function-call.js entity.name.function.js", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { diff --git a/test_static/colorize-results/test_myst.md.json b/test_static/colorize-results/test_myst.md.json index 6963f66..1fee128 100644 --- a/test_static/colorize-results/test_myst.md.json +++ b/test_static/colorize-results/test_myst.md.json @@ -33,7 +33,18 @@ } }, { - "c": " #", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "#", "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -77,7 +88,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -2189,7 +2211,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -2343,7 +2376,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", diff --git a/test_static/syntax-fixtures/colon_fence.md b/test_static/syntax-fixtures/colon_fence.md new file mode 100644 index 0000000..65487ee --- /dev/null +++ b/test_static/syntax-fixtures/colon_fence.md @@ -0,0 +1,416 @@ +src line: 1638 + +. +::: +< + > +::: +. +<pre><code>< + > +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1665 + +. +:: +foo +:: +. +<p>:: +foo +::</p> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1676 + +. +::: +aaa +~~~ +::: +. +<pre><code>aaa +~~~ +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1688 + +. +::: +aaa +``` +::: +. +<pre><code>aaa +``` +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1702 + +. +:::: +aaa +::: +:::::: +. +<pre><code>aaa +::: +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1729 + +. +::: +. +<pre><code></code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1736 + +. +::::: + +::: +aaa +. +<pre><code> +::: +aaa</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1749 + +. +> ::: +> aaa + +bbb +. +<blockquote> +<pre><code>aaa +</code></pre> +</blockquote> +<p>bbb</p> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1765 + +. +::: + + +::: +. +<pre><code> + +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1779 + +. +::: +::: +. +<pre><code></code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1791 + +. + ::: + aaa +aaa +::: +. +<pre><code>aaa +aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1803 + +. + ::: +aaa + aaa +aaa + ::: +. +<pre><code>aaa +aaa +aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1817 + +. + ::: + aaa + aaa + aaa + ::: +. +<pre><code>aaa + aaa +aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1833 + +. + ::: + aaa + ::: +. +<pre><code>::: +aaa +:::</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1848 + +. +::: +aaa + ::: +. +<pre><code>aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1858 + +. + ::: +aaa + ::: +. +<pre><code>aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1870 + +. +::: +aaa + ::: +. +<pre><code>aaa + :::</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1884 + +. +::: ::: +aaa +. +<pre><code class="language-:::">aaa</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1907 + +. +foo +::: +bar +::: +baz +. +<p>foo</p> +<pre><code>bar +</code></pre> +<p>baz</p> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1946 + +. +:::ruby +def foo(x) + return 3 +end +::: +. +<pre><code class="language-ruby">def foo(x) + return 3 +end +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1974 + +. +::::; +:::: +. +<pre><code class="language-;"></code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 1984 + +. +::: aa ::: +foo +. +<pre><code class="language-aa">foo</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 2007 + +. +::: +::: aaa +::: +. +<pre><code>::: aaa +</code></pre> +. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +src line: 2007 + +. +::: +::: aaa +::: +. +<pre><code>::: aaa +</code></pre> +. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Ending marker could be longer +. +::::: name ::::: + hello world +:::::::::::::::: +. +<pre><code class="language-name"> hello world +</code></pre> +. + +Nested blocks +. +::::: name +:::: name +xxx +:::: +::::: +. +<pre><code class="language-name">:::: name +xxx +:::: +</code></pre> +. + +Name could be adjacent to marker +. +:::name +xxx +::: +. +<pre><code class="language-name">xxx +</code></pre> +. + +They should terminate paragraphs +. +blah blah +::: name +content +::: +. +<p>blah blah</p> +<pre><code class="language-name">content +</code></pre> +. + +They could be nested in lists +. + - ::: name + - xxx + ::: +. +<ul> +<li> +<pre><code class="language-name">- xxx +</code></pre> +</li> +</ul> +. + +Or in blockquotes +. +> ::: name +> xxx +>> yyy +> zzz +> ::: +. +<blockquote> +<pre><code class="language-name">xxx +> yyy +zzz +</code></pre> +</blockquote> +. + +List indentation quirks +. + - ::: name + xxx + yyy + ::: + + - ::: name + xxx + yyy + ::: +. +<ul> +<li> +<pre><code class="language-name">xxx +yyy +</code></pre> +</li> +</ul> +<pre><code> +- ::: name + xxx +yyy +</code></pre> +. diff --git a/test_static/syntax-fixtures/myst_block.md b/test_static/syntax-fixtures/myst_block.md new file mode 100644 index 0000000..2e5d7f0 --- /dev/null +++ b/test_static/syntax-fixtures/myst_block.md @@ -0,0 +1,123 @@ + +Block Break: +. ++++ +. +<hr class="myst-block" /> +. + +Block Break Split Markers: +. + + + + + xfsdfsdf +. +<hr class="myst-block" /> +. + +Block Break Too Few Markers: +. +++ +. +<p>++</p> +. + +Block Break terminates other blocks: +. +a ++++ +- b ++++ +> c ++++ +. +<p>a</p> +<hr class="myst-block" /> +<ul> +<li>b</li> +</ul> +<hr class="myst-block" /> +<blockquote> +<p>c</p> +</blockquote> +<hr class="myst-block" /> +. + + +Target: +. +(a)= +. +<div class="myst-target"><a href="#a">(a)=</a></div> +. + + +Target terminates other blocks: +. +a +(a)= +- b +(a)= +> c +(a)= +. +<p>a</p> +<div class="myst-target"><a href="#a">(a)=</a></div><ul> +<li>b</li> +</ul> +<div class="myst-target"><a href="#a">(a)=</a></div><blockquote> +<p>c</p> +</blockquote> +<div class="myst-target"><a href="#a">(a)=</a></div> +. + +Comment: +. +% abc +. +<!-- abc --> +. + +Comment terminates other blocks: +. +a +% abc +- b +% abc +> c +% abc +. +<p>a</p> +<!-- abc --><ul> +<li>b</li> +</ul> +<!-- abc --><blockquote> +<p>c</p> +</blockquote> +<!-- abc --> +. + +Multiline comment: +. +a +% abc +% def +- b +% abc +%def +> c +%abc +% +%def +. +<p>a</p> +<!-- abc + def --><ul> +<li>b</li> +</ul> +<!-- abc +def --><blockquote> +<p>c</p> +</blockquote> +<!-- abc + +def --> +. diff --git a/tsconfig.json b/tsconfig.json index 985d98a..2754fbc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,13 @@ "target": "es6", "outDir": "out", "lib": [ - "es6" + "es6", + "es2018.regexp", // for group match in target syntax + "dom" ], "sourceMap": true, "rootDir": "src", + "esModuleInterop": true, /* Strict Type-Checking Option */ "strict": true, /* enable all strict type-checking options */ /* Additional Checks */ @@ -15,7 +18,11 @@ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ - "resolveJsonModule": true + "resolveJsonModule": true, + "typeRoots": [ + "./node_modules/@types", + "./types" + ] }, "exclude": [ "node_modules", diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..dbe83c2 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,3 @@ +declare module 'markdown-it-deflist'; +declare module 'markdown-it-footnote'; +declare module 'markdown-it-task-lists';