# Embedding code and data in documentation ## MarkdownSnippets/mdsnippets ## Overview The [MarkdownSnippets](https://github.com/SimonCropp/MarkdownSnippets) tool, also known as `mdsnippets`, is a [dotnet tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools) that extract snippets from code files and merges them into Markdown documents. Examples of things it can embed: - Code samples - Whole files, such as CSS files - Machine-generated `.md` and `.txt` files written by unit tests for the purpose of embedding in documentation. ### Automation via GitHub Action The Tasks project has automation via GitHub Action to update the documentation samples automatically via: - GitHub Action workflow: [update-docs-markdown.yml](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/.github/workflows/update-docs-markdown.yml) - The [logs from update-docs-markdown runs](https://github.com/obsidian-tasks-group/obsidian-tasks/actions/workflows/update-docs-markdown.yml) When this job updates any documentation files, it creates a [Pull Request](https://github.com/obsidian-tasks-group/obsidian-tasks/pulls?q=is%3Apr+label%3A%22type%3A+automated+update%22+label%3A%22scope%3A+documentation%22) for review and merging. ### Running mdsnippets To run mdsnippets on a development machine: 1. Install [MarkdownSnippets](https://github.com/SimonCropp/MarkdownSnippets), also known as `mdsnippets` 2. Run: ```bash mdsnippets && yarn run lint:markdown && git add --renormalize . ``` The above hard-won command line is to make sure that the output: - conforms to our `markdownlint` configuration - has the correct line endings on macOS The background to this is in [PR #1248](https://github.com/obsidian-tasks-group/obsidian-tasks/pull/1248). ### Configuring mdsnippets The configuration file for mdsnippets is: - [mdsnippets.json](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/mdsnippets.json) ## Adding new mdsnippets-maintained docs content ### Embedding a whole file as a code block, with 'snippet:' 1 **Add 'snippet:' instruction to embed the file** For example: - `snippet: ApprovalTestsDemo.test.ApprovalTests_JsonVerify.approved.json` 2 **Run mdsnippets to expand the 'snippet:' line** Run `mdsnippets` - see [[#Running mdsnippets]] Your `snippet: ...` line will be converted to this: <!-- snippet: ApprovalTestsDemo.test.ApprovalTests_JsonVerify.approved.json --> ```json { "name": "fred", "age": 30 } ``` <!-- endSnippet --> Notice how the above has syntax highlighting, as the `.json` file extension on the included file was used as the language in the generated code block. ### Embedding a whole file as a code block, with 'include:' 1 **Add 'include:' instruction to embed the file** For example: - `include: ApprovalTestsDemo.test.ApprovalTests_JsonVerify.approved.json` 2 **Run mdsnippets to expand the 'include:' line** Run `mdsnippets` - see [[#Running mdsnippets]] Your `include: ...` line will be converted to this: {<!-- include: ApprovalTestsDemo.test.ApprovalTests_JsonVerify.approved.json --> "name": "fred", "age": 30 }<!-- endInclude --> ### Embedding files in .obsidian folders by path mdsnippets normally only needs a filename, and not a full path, for any included files. However, for files in hidden directories, the full path is required. So this: - `snippet: resources/sample_vaults/Tasks-Demo/.obsidian/snippets/tasks-plugin-backlinks-small-grey.css` Generates this: <!-- snippet: resources/sample_vaults/Tasks-Demo/.obsidian/snippets/tasks-plugin-backlinks-small-grey.css --> ```css /* By David Phillips (autonia) https://github.com/autonia From https://github.com/obsidian-tasks-group/obsidian-tasks/discussions/622#discussioncomment-2649299 */ .tasks-backlink { font-size: 0.7em; opacity: 0.6; filter: grayscale(60%); } ``` <!-- endSnippet --> > [!Warning] Browser issue? > You should see 3 lines of comments at the top of the above sample, starting `/* By David Phillips...` > If you see 3 empty grey lines, your browser is for some reason hiding the comments, and for this page to be any use, you will unfortunately need to find a different browser. ### Embedding parts of files This section describes how to embed a section/snippet of source file in to Markdown, for easy writing of documentation, and keeping the docs up-to-date. 1 **Label the snippet with 'begin-snippet:' and 'end-snippet'** Think of a descriptive name for your snippet (file segment), and then surround it with two comments: - `begin-snippet: unique-name-of-snippet-across-your-repo` - `end-snippet` For example: ```ts // begin-snippet: approval-test-as-text test('SimpleVerify', () => { verify('Hello From Approvals'); }); // end-snippet ``` 2 **Put a 'snippet:' line in the documentation** In a Markdown documentation file, add a line `snippet: unique-name-of-snippet-across-your-repo` - For example: ```text snippet: approval-test-as-text ``` 3 **Run mdsnippets to expand the 'snippet:' line** Run `mdsnippets` - see [[#Running mdsnippets]] Your `snippet: ...` line will be converted to this: ````markdown <!-- snippet: approval-test-as-text --> ```ts test('SimpleVerify', () => { verify('Hello From Approvals'); }); ``` <!-- endSnippet --> ```` The HTML comments contain enough information for mdsnippets to be able to find the snippet file on each run, and update the Markdown if the included file changes. ## Example This page in the Tasks docs is almost entirely generated from content embedded with mdsnippets: - [ITS Theme](https://publish.obsidian.md/tasks/Reference/Status+Collections/ITS+Theme). Maintaining that amount of information, for multiple themes, would be an error-prone nightmare. ### The Inputs The following test source file exists purely to write out files for embedding in the documentation. - [DocsSamplesForStatuses.test.ts](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/DocumentationSamples/DocsSamplesForStatuses.test.ts) For the ITS theme, the above tests generate these `*.approved.*` files, using [[Approval Tests]]: - [tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Table.approved.md](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Table.approved.md) - [tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Tasks.approved.md](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Tasks.approved.md) - [tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Text.approved.txt](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/DocumentationSamples/DocsSamplesForStatuses.test.Theme_ITS_Text.approved.txt) And mdsnippets then embeds the above `*.approved.*` in to the source file. ### The documentation file The source file for the [ITS Theme](https://publish.obsidian.md/tasks/Reference/Status+Collections/ITS+Theme) page is: - [SlRvb's Alternate Checkboxes.md](https://raw.githubusercontent.com/obsidian-tasks-group/obsidian-tasks/main/docs/Reference/Status%20Collections/SlRvb's%20Alternate%20Checkboxes.md) Notice the `<!-- snippet:` and `<!-- include:` sections.