diff --git a/README.md b/README.md index 6e412ec3..8e339e7d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ A markdown-converter for [vscode][vscode] - [Custom Date-Formats](#custom-date-formats) - [Headers and Footers](#headers-and-footers) - [Including Table of Contents](#including-table-of-contents) + - [Including Markdown Fragment Files](#including-markdown-fragment-files) + - [Creating Block-Level Custom Containers](#creating-block-level-custom-containers) - [Third Party Markdown Extensions](#third-party-markdown-extensions) - [Assets](#assets) - [CSS- and JavaScript-Files](#css--and-javascript-files) @@ -191,6 +193,32 @@ Furthermore, the `markdownConverter.Parser.Toc.Levels` allows you to choose whic } ``` +## Including Markdown Fragment Files +It is now possible to fragment the document in multiple sections and to merge them all into one. This way, it's possible to work on separate fragments at the same time without having to bear with conflicts during editing. Add fragments using this syntax: +```md +!!!include(file.md)!!! +``` + +## Creating Block-Level Custom Containers +MarkdownConverter allows you to apply CSS classes to specific parts of your document. +This feature can be used with the following syntax: + +In your Markdown file: +```md +:::class + +Text Here + +::: +``` + +In your CSS file: +```css +div.class { + // Custom CSS Here + } +``` + ## Third Party Markdown Extensions If you want to use third party markdown-extensions in your documents (such as the [Markdown Preview Mermaid Support], [Markdown Footnote] or [Markdown Emoji]), you might want to install the extensions of your choice and enable the `markdownConverter.Parser.SystemParserEnabled` setting which makes `MarkdownConverter` use VSCode's built-in `markdown-it` parser with all markdown extensions enabled. diff --git a/package-lock.json b/package-lock.json index 01a2bae3..a8de56a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "markdown-converter", "version": "5.0.1", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, "packages": { "": { @@ -27,6 +27,7 @@ "markdown-it": "^12.2.0", "markdown-it-anchor": "^8.3.1", "markdown-it-checkbox": "^1.1.0", + "markdown-it-container": "^3.0.0", "markdown-it-emoji": "^2.0.0", "markdown-it-table-of-contents": "^0.5.2", "multi-integer-range": "^4.0.9", @@ -52,6 +53,7 @@ "@types/highlight.js": "^9.12.4", "@types/lodash.clonedeep": "^4.5.6", "@types/lodash.kebabcase": "^4.1.6", + "@types/markdown-it-container": "^2.0.4", "@types/markdown-it-emoji": "^2.0.2", "@types/minimist": "^1.2.2", "@types/mocha": "^9.0.0", @@ -69,6 +71,7 @@ "eslint": "^7.32.0", "json5-loader": "^4.0.1", "lodash.kebabcase": "^4.1.1", + "markdown-it-include": "^2.0.0", "minimist": "^1.2.5", "mocha": "^9.1.2", "ovsx": "^0.2.1", @@ -1665,6 +1668,15 @@ "@types/mdurl": "*" } }, + "node_modules/@types/markdown-it-container": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/markdown-it-container/-/markdown-it-container-2.0.4.tgz", + "integrity": "sha512-QgzDCr8OWtWktWtlwPT908sKqZqSHUEaxTH/uVz68tYd6bsCS3defHLzN2rFeoKJ3q344qG0dWQ42K4UQSBqcw==", + "dev": true, + "dependencies": { + "@types/markdown-it": "*" + } + }, "node_modules/@types/markdown-it-emoji": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz", @@ -6021,11 +6033,28 @@ "underscore": "^1.8.2" } }, + "node_modules/markdown-it-container": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz", + "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==" + }, "node_modules/markdown-it-emoji": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.0.tgz", "integrity": "sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==" }, + "node_modules/markdown-it-include": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-include/-/markdown-it-include-2.0.0.tgz", + "integrity": "sha512-wfgIX92ZEYahYWiCk6Jx36XmHvAimeHN420csOWgfyZjpf171Y0xREqZWcm/Rwjzyd0RLYryY+cbNmrkYW2MDw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "markdown-it": ">=8.4.2" + } + }, "node_modules/markdown-it-table-of-contents": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.5.2.tgz", @@ -10468,6 +10497,15 @@ "@types/mdurl": "*" } }, + "@types/markdown-it-container": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/markdown-it-container/-/markdown-it-container-2.0.4.tgz", + "integrity": "sha512-QgzDCr8OWtWktWtlwPT908sKqZqSHUEaxTH/uVz68tYd6bsCS3defHLzN2rFeoKJ3q344qG0dWQ42K4UQSBqcw==", + "dev": true, + "requires": { + "@types/markdown-it": "*" + } + }, "@types/markdown-it-emoji": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz", @@ -13807,11 +13845,23 @@ "underscore": "^1.8.2" } }, + "markdown-it-container": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz", + "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==" + }, "markdown-it-emoji": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.0.tgz", "integrity": "sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==" }, + "markdown-it-include": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-include/-/markdown-it-include-2.0.0.tgz", + "integrity": "sha512-wfgIX92ZEYahYWiCk6Jx36XmHvAimeHN420csOWgfyZjpf171Y0xREqZWcm/Rwjzyd0RLYryY+cbNmrkYW2MDw==", + "dev": true, + "requires": {} + }, "markdown-it-table-of-contents": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.5.2.tgz", diff --git a/package.json b/package.json index 6170d733..204683b8 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "markdown-it": "^12.2.0", "markdown-it-anchor": "^8.3.1", "markdown-it-checkbox": "^1.1.0", + "markdown-it-container": "^3.0.0", "markdown-it-emoji": "^2.0.0", "markdown-it-table-of-contents": "^0.5.2", "multi-integer-range": "^4.0.9", @@ -95,6 +96,7 @@ "@types/highlight.js": "^9.12.4", "@types/lodash.clonedeep": "^4.5.6", "@types/lodash.kebabcase": "^4.1.6", + "@types/markdown-it-container": "^2.0.4", "@types/markdown-it-emoji": "^2.0.2", "@types/minimist": "^1.2.2", "@types/mocha": "^9.0.0", @@ -112,6 +114,7 @@ "eslint": "^7.32.0", "json5-loader": "^4.0.1", "lodash.kebabcase": "^4.1.1", + "markdown-it-include": "^2.0.0", "minimist": "^1.2.5", "mocha": "^9.1.2", "ovsx": "^0.2.1", diff --git a/src/System/Documents/EnvironmentKey.ts b/src/System/Documents/EnvironmentKey.ts new file mode 100644 index 00000000..6052b7d5 --- /dev/null +++ b/src/System/Documents/EnvironmentKey.ts @@ -0,0 +1,10 @@ +/** + * Represents a key + */ +export enum EnvironmentKey +{ + /** + * Indicates the {@link RootDir `RootDir`} setting. + */ + RootDir = "markdown-converter-root-dir" +} diff --git a/src/System/Documents/MarkdownFragment.ts b/src/System/Documents/MarkdownFragment.ts index a77ccfb7..26578769 100644 --- a/src/System/Documents/MarkdownFragment.ts +++ b/src/System/Documents/MarkdownFragment.ts @@ -1,5 +1,7 @@ +import { dirname } from "upath"; import { Document } from "./Document"; import { DocumentFragment } from "./DocumentFragment"; +import { EnvironmentKey } from "./EnvironmentKey"; /** * Represents a fragment of a document with markdown-support. @@ -25,6 +27,10 @@ export class MarkdownFragment extends DocumentFragment */ protected override async RenderContent(): Promise { - return this.Document.Parser.render(await super.RenderContent()); + return this.Document.Parser.render( + await super.RenderContent(), + { + [EnvironmentKey.RootDir]: this.Document.FileName ? dirname(this.Document.FileName) : null + }); } } diff --git a/src/System/Tasks/ConversionRunner.ts b/src/System/Tasks/ConversionRunner.ts index f1e50e17..6e89922f 100644 --- a/src/System/Tasks/ConversionRunner.ts +++ b/src/System/Tasks/ConversionRunner.ts @@ -5,7 +5,11 @@ import { highlight } from "highlight.js"; import cloneDeep = require("lodash.clonedeep"); import MarkdownIt = require("markdown-it"); import checkbox = require("markdown-it-checkbox"); +import markdownContainer = require("markdown-it-container"); import emoji = require("markdown-it-emoji"); +import markdownInclude = require("markdown-it-include"); +import StateCore = require("markdown-it/lib/rules_core/state_core"); +import Token = require("markdown-it/lib/token"); import format = require("string-template"); import { convert, parse } from "twemoji"; import { dirname, isAbsolute, join, resolve } from "upath"; @@ -25,6 +29,7 @@ import { WebScript } from "../Documents/Assets/WebScript"; import { AttributeKey } from "../Documents/AttributeKey"; import { Document } from "../Documents/Document"; import { EmojiType } from "../Documents/EmojiType"; +import { EnvironmentKey } from "../Documents/EnvironmentKey"; import { ListType } from "../Documents/ListType"; import { Anchor } from "../Documents/Plugins/MarkdownAnchorPlugin"; import { TOC } from "../Documents/Plugins/MarkdownTocPlugin"; @@ -489,6 +494,43 @@ export class ConversionRunner }; } + /** + * Add Markdown IT Container + */ + parser.use( + markdownContainer, + "", + { + validate(name: string) + { + return name.trim().length; + }, + render(token: Token[], id: number) + { + if (token[id].info.trim() !== "") + { + return `
\n`; + } + else + { + return "
\n"; + } + } + }); + + /** + * Add Markdown IT Include + */ + parser.use( + markdownInclude, + { + getRootDir: (options: any, state: StateCore) => + { + return state.env[EnvironmentKey.RootDir] ?? "."; + }, + includeRe: /!{3}\s*include(.+?)!{3}/i + }); + return parser; } diff --git a/src/System/markdown-it-include.d.ts b/src/System/markdown-it-include.d.ts new file mode 100644 index 00000000..fa14c979 --- /dev/null +++ b/src/System/markdown-it-include.d.ts @@ -0,0 +1 @@ +declare module "markdown-it-include"; diff --git a/webpack.config.ts b/webpack.config.ts index a9f4336b..120acfb7 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -41,7 +41,8 @@ export = (env: any, argv: any) => path: resolve(__dirname, "lib"), filename: "[name].js", libraryTarget: "commonjs2", - devtoolFallbackModuleFilenameTemplate: "../[resource-path]" + devtoolFallbackModuleFilenameTemplate: "../[resource-path]", + hashFunction: "xxhash64" }, devtool: "source-map", externals,