{"id":17973146,"url":"https://github.com/szkiba/mdcode","last_synced_at":"2025-03-25T12:33:16.526Z","repository":{"id":216185345,"uuid":"740676029","full_name":"szkiba/mdcode","owner":"szkiba","description":"Markdown code block authoring tool","archived":false,"fork":false,"pushed_at":"2025-02-18T15:58:19.000Z","size":64,"stargazers_count":22,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-20T08:44:56.409Z","etag":null,"topics":["documentation-testing","markdown","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/szkiba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-08T20:46:40.000Z","updated_at":"2025-02-10T16:59:03.000Z","dependencies_parsed_at":"2024-01-11T23:51:48.301Z","dependency_job_id":"f2ed3b0f-1f6c-42fc-bc6c-58494976cb52","html_url":"https://github.com/szkiba/mdcode","commit_stats":null,"previous_names":["szkiba/mdcode"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/szkiba%2Fmdcode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/szkiba%2Fmdcode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/szkiba%2Fmdcode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/szkiba%2Fmdcode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/szkiba","download_url":"https://codeload.github.com/szkiba/mdcode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245463052,"owners_count":20619602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["documentation-testing","markdown","testing"],"created_at":"2024-10-29T16:27:38.281Z","updated_at":"2025-03-25T12:33:15.789Z","avatar_url":"https://github.com/szkiba.png","language":"Go","funding_links":[],"categories":["Markdown Building Blocks"],"sub_categories":["Markdown Libraries \u0026 Tools"],"readme":"# ｍｄｃｏｄｅ\n\n**Markdown code block authoring tool**\n\nThe `mdcode` command-line tool allows code blocks embedded in a markdown document to be developed in the usual way. During the development of the code blocks, the usual tools and methods can be used. This makes the embedded codes testable, which is especially important for example codes. There is no worse developer experience than a faulty sample code.\n\nHere is a simple example code for a factorial calculation:\n\n**go**\n\u003c!--\u003cscript type=\"text/markdown\"\u003e\n```go file=README_test.go outline=true\npackage main\n\nimport \"testing\"\n\n// #region function\n// #endregion\n\nfunc Test_factorial(t *testing.T) {\n\tt.Parallel()\n\n\ttestvect := []uint64{1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800}\n\n\tfor idx, expected := range testvect {\n\t\tif actual := factorial(uint64(idx)); actual != expected {\n\t\t\tt.Errorf(\"factorial(%d) should be %d but got %d\", idx, expected, actual)\n\t\t}\n\t}\n}\n```\n\u003c/script\u003e--\u003e\n\n```go file=README_test.go region=function\nfunc factorial(n uint64) uint64 {\n\tif n \u003e 1 {\n\t\treturn n * factorial(n-1)\n\t}\n\n\treturn 1\n}\n\n```\n\n**JavaScript**\n\n\u003c!--\u003cscript type=\"text/markdown\"\u003e\n```js file=README.test.js outline=true\nconst assert = require(\"node:assert\");\nconst test = require(\"node:test\");\n\n// #region function\n// #endregion\n\nconst testvect = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800];\n\ntest(\"factorial with test vector\", (t) =\u003e {\n    for (var i = 0; i \u003c testvect.length; i++) {\n        assert.equal(factorial(i), testvect[i]);\n    }\n})\n```\n\u003c/script\u003e--\u003e\n\n```js file=README.test.js region=function\nfunction factorial(n) {\n    if (n \u003e 1) {\n        return n * factorial(n - 1)\n    }\n\n    return 1\n}\n\n```\n\nAt first glance, there is nothing special about this. *However, these code blocks are testable!* \n\nThis document includes the necessary code for testing within invisible code blocks. By examining the [source of this document](https://github.com/szkiba/mdcode/blob/master/README.md?plain=1), you can observe how effortlessly code blocks, even invisible ones, can be embedded using `mdcode`.\n\nCode blocks embedded in this document can be saved to files using the [`mdcode extract`](#mdcode-extract) command. A `README_test.go` and a `README.test.js` file will be created in the current directory. After modification, the code blocks can be updated from these files to the document using the [`mdcode update`](#mdcode-update) command.\n\nAfter the modification, it is advisable to test the above examples using the following commands:\n\n```sh name=test\ngo test ./...\nnode --test\n```\n\nSince the above code block has a name (`test`), it can also be run with the [`mdcode run`](#mdcode-run) command:\n\n```\nmdcode run -n test\n```\n\nMore examples can be found in the [examples](examples/) directory and in the [tutorial](docs/testable-markdown-code-blocks.md).\n\n### Features\n\n- include source files as code blocks in the markdown document\n- update the code blocks in the markdown document\n- save markdown code blocks to source files\n- supports source file fragments using `#region` comments\n- supports invisible (not rendered) code blocks\n- allows you to add metadata to code blocks\n- programming language agnostic\n- dump code blocks as tar archive\n\n### Use Cases\n\n**Develop the example/tutorial codes as you would any other code**\n  - use your favorite IDE, toolchain\n  - use any test framework for testing\n  - integrate example code testing into the build process\n  - use [`mdcode update`](#mdcode-update) to update example code in markdown documents\n\n**Write example code directly in the markdown documents**\n  - use [`mdcode extract`](#mdcode-extract) to extract code blocks and save them to files\n  - use any test framework for testing\n  - integrate example code testing into the build process\n\n**Create a self-contained markdown tutorial document**\n  - use [`mdcode update`](#mdcode-update) to embed source fragments\n  - use [`mdcode update`](#mdcode-update) to embed additional files (package.json, go.mod, etc.) as invisible code blocks\n  - use [`mdcode extract`](#mdcode-extract) to extract working examples from the markdown documemt\n\n**Save all examples for later use**\n  - use [`mdcode dump`](#mdcode-dump) to create tar archive from code blocks\n\n### Install\n\nPrecompiled binaries can be downloaded and installed from the [Releases](https://github.com/szkiba/mdcode/releases) page.\n\nIf you have a go development environment, the installation can also be done with the following command:\n\n```\ngo install github.com/szkiba/mdcode@latest\n```\n\nIt can even be run without installation using the following command:\n\n```\ngo run github.com/szkiba/mdcode@latest\n```\n\n### Usage\n\nCheck [CLI Reference](#cli-reference) section for detailed command line usage.\n\n## Concepts\n\n### Metadata\n\n\u003c!-- #region metadata --\u003e\nMetadata can be specified for code blocks. These metadata can be used to modify the operation of the subcommands (for example, they can be used for filtering).\n\nThe [CommonMark specification](https://spec.commonmark.org/current/) allows the use of a so-called [info-string](https://spec.commonmark.org/current/#info-string) in the fenced code block. The first word of the *info-string* typically indicates the programming language, the meaning of the remaining part is not defined by the specification.\n\n`mdcode` uses the part after the first word of the *info-string* to specify metadata. The metadata can be entered in JSON format and in a simple, space-separated `name=\"value\"` format list (where the use of quotation marks is only necessary for values containing spaces). The latter form is more readable, but the JSON format is more portable.\n\nExample name=\"value\" list metadata:\n\n    ```js file=sample.js region=factorial\n\n    ```\n\nExample JSON metadata:\n\n    ```js {\"file\":\"sample.js\",\"region\":\"factorial\"}\n\n    ```\n\nMetadata used by `mdcode`:\n\nname      | description\n----------|-------------------------------------------------\n`file`    | name of the file assigned to the code block\n`region`  | name of region within file (if any)\n`outline` | true if the code block is an outline of the file\n\nThe only mandatory metadata is `file`.\n\u003c!-- #endregion metadata --\u003e\n\n### Filtering\n\n\u003c!-- #region filtering --\u003e\nBy default, `mdcode` work with all code blocks in a markdown document. It is possible to filter code blocks based on programming language or metadata. In this case, `mdcode` ignores code blocks that do not meet the filter criteria.\n\nA language filter pattern can be specified using the `--lang` flag. Then only code blocks with a language matching the pattern will be processed. For example, filtering for code blocks containing JavaScript code:\n\n\tmdcode --lang js\n\t\t\nA file name filtering pattern can be specified using the `--file` flag. Then only code blocks with `file` metadata matching the pattern will be processed. For example, filtering for code blocks containing the file named `examples/foo.js` (or parts of it):\n\n\tmdcode --file examples/foo.js\n\nThe `--meta` flag can be used to specify an arbitrary metadata filtering pattern. Then only code blocks with metadata matching the pattern are processed. For example, filtering for code blocks that have metadata named `name` and its value is `simple`:\n\n\tmdcode --meta name=simple\n\nSpecifying several different filter criteria (e.g. language and metadata, or two different metadata) each criteria must be met (and relation).\n\nStandard glob patterns can be used in programming language and metadata filter criteria.\n\npattern          | match\n-----------------|--------------------------------------------------------------\n`*`              | matches any sequence of non-separator characters\n`**`             | matches any sequence of characters\n`?`              | matches any single non-separator character\n`[` range `]`    | character in range\n`[` `!` range `]`| character not in range \n`{` list `}`     | matches any of comma-separated (without spaces) patterns\nc                | matches character c (c != `*`, `**`, `?`, `\\`, `[`, `{`, `}`)\n`\\` c            | matches character c\n\nrange     | match\n----------|-----------------------------------------\nc         | matches character c (c != `\\`, `-`, `]`)\n`\\` c     | matches character c\nlo `-` hi | matches character c for lo \u003c= c \u003c= hi\n\nExamples of filter pattern use:\n\n    mdcode extract --meta file='examples/**/*.go'\n    mdcode extract --lang '{go,js}'\n\nFiltering with frequently used metadata can also be done using dedicated flags.\n\nflag             | shorthand    | equivalent\n-----------------|--------------|----------------------\n`--file pattern` | `-f pattern` | `--meta file=pattern`\n\u003c!-- #endregion filtering --\u003e\n\n### Regions\n\n\u003c!-- #region regions --\u003e\nIn addition to embedding entire files, `mdcode` supports the use of file regions. Named regions can be used in the source code of any programming language. The beginning of the region is marked by a comment line with the content `#region name` and the end by a comment line with the content `#endregion`.\n\nFor example, in the case of programming languages using C-style line comments (C, C++, Java, JavaScript, go, etc.):\n\n    // #region common\n\n    // #endregion\n\nIn the case of programming languages using shell-style line comments (Python, sh, bash, etc.):\n\n    # #region common\n\n    # #endregion\n\nOr if only block comments can be used (CSS):\n\n    /* #region common */\n\n    /* #endregion */\n\nRegions marked in this way are used by IDEs to collapse parts of the source code.\n\nIn the case of `mdcode`, regions can be referenced with the `region` metadata. If a region is specified for a code block, the subcommand (update or extract) applies only to the specified region of the file. That is, the update command only embeds the specified region from the file to the markdown document, and the extract command overwrites only the specified region in the file.\n\n`mdcode` can handle regions in any programming language, the only requirement is that the comment indicating the beginning and end of the region is placed in a separate line containing only the given comment.\n\u003c!-- #endregion regions --\u003e\n\n### Invisible\n\n\u003c!-- #region invisible --\u003e\nIt is possible to use invisible code blocks. This is useful, for embedding test code or additional files in the markdown document. The invisible code block is also useful if you want to embed the entire file, but only want to display certain parts of it.\n\nA markdown document can contain HTML elements. Unknown or unsupported HTML elements are usually not rendered by markdown renderers. Taking advantage of this, `mdcode` supports hiding code blocks using the standard `\u003cscript\u003e` HTML element:\n\n    \u003cscript type=\"text/markdown\"\u003e\n    ```js file=sample.js region=factorial\n\n    ```\n    \u003c/script\u003e\n\nUnfortunately, the GitHub markdown renderer renders the content of unsupported HTML elements as text. Therefore, `mdcode` also supports the use of a `\u003cscript\u003e` element surrounded by an HTML comment to hide a code block.\n\n    \u003c!--\u003cscript type=\"text/markdown\"\u003e\n    ```js file=sample.js region=factorial\n\n    ```\n    \u003c/script\u003e--\u003e\n\n*It is important to note that the opening character of the comment and the opening tag of the script element must be placed on the same line. Similarly, the closing tag of the script element and the closing tag of the comment must also be placed on the same line.*\n\u003c!-- #endregion invisible --\u003e\n\n**Highlighting invisible code block**\n\nTo highlight markdown within an HTML script element, the \n[Markdown Script Tag](https://marketplace.visualstudio.com/items?itemName=sissel.markdown-script-tag) extension can be used in Visual Studio Code.\n\n### Outline\n\n\u003c!-- #region outline --\u003e\nWhen using regions, only parts of the source file are embedded in the markdown document. If we want to create a self-contained markdown document, the `true` value of the `outline` metadata can be used for this purpose.\n\nIn this case, only parts of the source file other than the region comments are embedded in the markdown document (and the empty region comments).\n\nThe outline flag is typically used in an invisible code block preceding the visible regions. Since the `mdcode extract` command processes the code blocks sequentially, the code block marked with an `outline` first overwrites the file, then the code blocks containing the named regions are inserted in their place.\n\u003c!-- #endregion outline --\u003e\n\nHere is the invisible outline code block at the beginning of this document:\n\n    \u003c!--\u003cscript type=\"text/markdown\"\u003e\n    ```go file=README_test.go outline=true\n    package main\n\n    import \"testing\"\n\n    // #region function\n    // #endregion\n\n    func Test_factorial(t *testing.T) {\n      t.Parallel()\n\n      testvect := []uint64{1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800}\n\n      for idx, expected := range testvect {\n        if actual := factorial(uint64(idx)); actual != expected {\n          t.Errorf(\"factorial(%d) should be %d but got %d\", idx, expected, actual)\n        }\n      }\n    }\n    ```\n    \u003c/script\u003e--\u003e\n\nAnd here is the code block containing the corresponding region reference:\n\n    ```go file=README_test.go region=function\n    func factorial(n uint64) uint64 {\n      if n \u003e 1 {\n        return n * factorial(n-1)\n\t    }\n\n\t    return 1\n    }\n    ```\n\n## Development\n\n### Tasks\n\nThis section contains a description of the tasks performed during development. If you have the [xc (Markdown defined task runner)](https://github.com/joerdav/xc) command-line tool, individual tasks can be executed simply by using the `xc task-name` command.\n\n\u003cdetails\u003e\u003csummary\u003eClick to expand\u003c/summary\u003e\n\n#### lint\n\nRun the static analyzer.\n\n```\ngolangci-lint run\n```\n\n#### test\n\nRun the tests.\n\n```\ngo test -count 1 -race -coverprofile=build/coverage.txt ./...\n```\n\n#### coverage\n\nView the test coverage report.\n\n```\ngo tool cover -html=build/coverage.txt\n```\n\n#### build\n\nBuild the executable binary.\n\nThis is the easiest way to create an executable binary (although the release process uses the goreleaser tool to create release versions).\n\n```\ngo build -ldflags=\"-w -s\" -o build/mdcode .\n```\n\n#### snapshot\n\nCreating an executable binary with a snapshot version.\n\nThe goreleaser command-line tool is used during the release process. During development, it is advisable to create binaries with the same tool from time to time.\n\n```\ngoreleaser build --snapshot --clean --single-target -o build/mdcode\n```\n\n#### doc\n\nUpdating the documentation.\n\nSome parts of the documentation, such as the [CLI Reference](#cli-reference), example codes, are automatically generated.\n\n```\ngo generate\n```\n\n#### doc-test\n\nTesting the generated documentation.\n\n```\ngo generate\ngo test ./...\nnode --test\n```\n\n#### clean\n\nDelete the build directory.\n\n```\nrm -rf build\n```\n\n#### all\n\nRun all tasks.\n\nRequires: lint,test,doc,doc-test,build,snapshot\n\n\u003c/details\u003e\n\n## CLI Reference\n\nThis chapter contains the reference documentation for the command line interface. In addition to the commands described here, additional help topics are available from the command line. To view them, the topic name must be specified as a subcommand.\n\n\u003c!-- #region cli --\u003e\nAdditional help topics:\n* `mdcode filtering` - [Pattern based filtering](#filtering)\n* `mdcode invisible` - [Invisible code blocks](#invisible)\n* `mdcode metadata` - [Code block metadata](#metadata)\n* `mdcode outline` - [Embedding the file structure](#outline)\n* `mdcode regions` - [Handling file regions](#regions)\n---\n\n## mdcode\n\nMarkdown code block authoring tool\n\n### Synopsis\n\nLists the code blocks (with file metadata) from the markdown document.\n\nThe optional argument of the `mdcode` command is the name of the markdown file. If it is missing, the `README.md` file in the current directory (if it exists) is processed.\n\n\n```\nmdcode [flags] [filename]\n```\n\n### Flags\n\n```\n  -f, --file strings          file filter (default [?*])\n  -h, --help                  help for mdcode\n      --json                  generate JSON output\n  -l, --lang strings          language filter (default [?*])\n  -m, --meta stringToString   metadata filter (default [])\n  -o, --output string         output file (default: standard output)\n```\n\n### SEE ALSO\n\n* [mdcode dump](#mdcode-dump)\t - Dump markdown code blocks\n* [mdcode extract](#mdcode-extract)\t - Extract markdown code blocks to the file system\n* [mdcode run](#mdcode-run)\t - Run shell commands on markdown code blocks\n* [mdcode update](#mdcode-update)\t - Update markdown code blocks from the file system\n\n---\n## mdcode dump\n\nDump markdown code blocks\n\n### Synopsis\n\nDump markdown code blocks as tar archive\n\nCreating a tar format archive from code blocks that meet the filtering criteria. By default, it writes to standard output, but it can also be directed to file with the `--output` flag.\n\nA base directory can be specified with the `--dir` flag, all files will be created under this directory.\n\nThe optional argument of the `mdcode dump` command is the name of the markdown file. If it is missing, the `README.md` file in the current directory (if it exists) is processed.\n\n\n```\nmdcode dump  [flags] [filename]\n```\n\n### Flags\n\n```\n  -d, --dir string      base directory name (default \".\")\n  -h, --help            help for dump\n  -o, --output string   output file (default: standard output)\n  -q, --quiet           suppress the status output\n```\n\n### Global Flags\n\n```\n  -f, --file strings          file filter (default [?*])\n  -l, --lang strings          language filter (default [?*])\n  -m, --meta stringToString   metadata filter (default [])\n```\n\n### SEE ALSO\n\n* [mdcode](#mdcode)\t - Markdown code block authoring tool\n\n---\n## mdcode extract\n\nExtract markdown code blocks to the file system\n\n### Synopsis\n\nWriting all code blocks matching the filter criteria to the file system\n\nThe code blocks are written to the file named in the `file` metadata. The file name is relative to the current directory or to the directory specified with the `--dir` flag.\n\nThe code block may include `region` metadata, which contains the name of the region. In this case, the code block is written to the appropriate part of the file marked with the `#region` comment.\n\nThe optional argument of the `mdcode extract` command is the name of the markdown file. If it is missing, the `README.md` file in the current directory (if it exists) is processed.\n\n\n```\nmdcode extract [flags] [filename]\n```\n\n### Flags\n\n```\n  -d, --dir string   base directory name (default \".\")\n  -h, --help         help for extract\n  -q, --quiet        suppress the status output\n```\n\n### Global Flags\n\n```\n  -f, --file strings          file filter (default [?*])\n  -l, --lang strings          language filter (default [?*])\n  -m, --meta stringToString   metadata filter (default [])\n```\n\n### SEE ALSO\n\n* [mdcode](#mdcode)\t - Markdown code block authoring tool\n\n---\n## mdcode run\n\nRun shell commands on markdown code blocks\n\n### Synopsis\n\nExtract code blocks to the file system and run shell commands on them\n\nThe code blocks are written to the file named in the `file` metadata.\n\nThe code block may include `region` metadata, which contains the name of the region. In this case, the code block is written to the appropriate part of the file marked with the `#region` comment.\n\nThe optional argument of the `mdcode run` command is the name of the markdown file. If it is missing, the `README.md` file in the current directory (if it exists) is processed.\n\nThis can be followed by a double dash (`--`) and then the shell command line to be executed (even a complex command, such as `for`).\n\nAlternatively, the commands to be executed can be embedded in a code block in the document. In this case, the language must be `sh` and it is necessary to name the code block with the metadata `name`. The name of the code block containing the commands can be specified with the `--name` flag (if not, the first code block containing the `sh` language and `name` metadata will be executed).\n\nCode blocks are extracted to a temporary directory. This directory will be the current directory when running the commands. The temporary directory is deleted after executing the commands (deletion can be prevented by using the `--keep` flag). Instead of a temporary directory, the name of the directory to be used can be specified with the `--dir` flag. In this case, of course, the directory is not deleted after executing the commands.\n\n\n```\nmdcode run [flags] [filename] [-- commands]\n```\n\n### Flags\n\n```\n  -d, --dir string    base directory name (default \".\")\n  -h, --help          help for run\n  -k, --keep          don't remove temporary directory\n  -n, --name string   code block name contains commands\n  -q, --quiet         suppress the status output\n```\n\n### Global Flags\n\n```\n  -f, --file strings          file filter (default [?*])\n  -l, --lang strings          language filter (default [?*])\n  -m, --meta stringToString   metadata filter (default [])\n```\n\n### SEE ALSO\n\n* [mdcode](#mdcode)\t - Markdown code block authoring tool\n\n---\n## mdcode update\n\nUpdate markdown code blocks from the file system\n\n### Synopsis\n\nUpdate all code blocks that meet the filter criteria from the file system\n\nThe code blocks are read from the file named in the `file` metadata. The file name is relative to the current directory or to the directory specified with the `--dir` flag.\n\nThe code block may include `region` metadata, which contains the name of the region. In this case, the code block is read from the appropriate part of the file marked with the `#region` comment.\n\nThe optional argument of the `mdcode update` command is the name of the markdown file. If it is missing, the `README.md` file in the current directory (if it exists) is processed.\n\n\n```\nmdcode update [flags] [filename]\n```\n\n### Flags\n\n```\n  -d, --dir string   base directory name (default \".\")\n  -h, --help         help for update\n  -q, --quiet        suppress the status output\n```\n\n### Global Flags\n\n```\n  -f, --file strings          file filter (default [?*])\n  -l, --lang strings          language filter (default [?*])\n  -m, --meta stringToString   metadata filter (default [])\n```\n\n### SEE ALSO\n\n* [mdcode](#mdcode)\t - Markdown code block authoring tool\n\n\u003c!-- #endregion cli --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fszkiba%2Fmdcode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fszkiba%2Fmdcode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fszkiba%2Fmdcode/lists"}