https://github.com/ifiokjr/comment_templates
Update markdown, TypeScript, and JavaScript files in place using comments as template tags.
https://github.com/ifiokjr/comment_templates
Last synced: 3 months ago
JSON representation
Update markdown, TypeScript, and JavaScript files in place using comments as template tags.
- Host: GitHub
- URL: https://github.com/ifiokjr/comment_templates
- Owner: ifiokjr
- License: mit
- Created: 2022-06-26T15:48:50.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2022-06-26T16:05:18.000Z (almost 3 years ago)
- Last Synced: 2025-01-14T10:57:21.464Z (5 months ago)
- Language: TypeScript
- Size: 41 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- Changelog: changelog.md
- License: license
Awesome Lists containing this project
README
# comment_templates
> Update markdown, TypeScript, and JavaScript files in place using comments as template tags.
## Why?
Often, while developing a project, you will want to automatically update sections of content in the file. For example:
- The `version` has been updated and should be reflected in multiple files.
- The API has changed and the autogenerated documentation needs to be updated in the `readme.md` file.The solution is to wrap the content you want to replace in a language specific comment block. A build command is then run which injects values into the comment tag while preserving the tags. This means that blocks can be updated multiple times with new data.
## API
### `commentTemplate`
```ts
declare function commentTemplate(props: CommentTemplateProps): string;
```
#### Description
Provide a string which contains template tags (using html and slash comments) that should be replaced with the variables provided.
```md
Placeholder text
```The above code will replace `Placeholder text` with the value of the `name` variable.
Unlike usual template formats, the wrapping comment tags are not not processed by the template engine. Only the wrapped content is replaced. This allows the template values to be updated continually.
Since `html` comments don't work within markdown codeblocks you should pass the full codeblock as one of the variable values. You can use pipes to make sure the content is properly wrapped as a codeblock.
```md
|
```The above would transform the variable value of sample into a codeblock with the language `tsx`.
- `|` is used to separate the pipes.
- `:` is used to apply different arguments to the underlying pipe transformation.
- Multiple pipes can be applied to a single value.```md
```
The supported pipe names are.
- `trim`: `|trim:null` trim all whitespace from the start and end of the content.
- `trimStart`: `|trim:null` trim all whitespace from the start of the content.
- `trimEnd`: `|trim:null` trim all whitespace from the end of the content.
- `string`: `|string:true` will wrap the value in single quotes. |string:false` will wrap the value in double quotes.
- `prefix`: `|prefix:"prefix"` will prefix the value with the provided string.
- `suffix`: `|suffix:"suffix"` will suffix the value with the provided string.
- `codeblock`: `|codeblock:"language"` will wrap the value in a codeblock with the provided language and set the indentation.
- `indent`: `|indent:" "` will indent each line by the provided string. This can be used to provide custom prefixes like `|indent:" * "` to
- `code`: `|code:null` will wrap the value in inline code `\`` backticks.
- `replace`: `|replace:"search,replace"` will replace the search string with the replacement where the `,` is used to split the string.The supported pipe arguments are `true`, `false`, `null`, any number `0123456789_` and any string wrapped in double quotes `"string"`
**NOTE**: The pipe arguments are not processed with regex and at the moment the regex is timing out when a single pipe is used without arguments. In order to use a single pipe, please provide an argument, even if it is an empty string.
#### Examples
```ts
import {
commentTemplate,
} from "https://deno.land/x/[email protected]/mod.ts";
import { assertEquals } from "./tests/deps.ts";const exampleVersion = "2.1.0";
const exampleName = "Comment Template!";
const fileUrl = new URL("tests/fixtures/sample.md", import.meta.url);
const content = await Deno.readTextFile(fileUrl);// Transform and use the variables in the content.
const transformed = commentTemplate({
content,
variables: { exampleVersion, exampleName },
});assertEquals(
transformed,
`# CommentTemplate!\`@2.1.0\`\n`,
);
```**Before:** `readme.md`
```md
#
```**After:** `readme.md`
```md
# package`@2.1.0`
```### `CommentTemplateProps`
```ts
interface CommentTemplateProps {
content: string;
variables: CommentTemplateVariables;
throwIfMissingVariable?: boolean;
patterns?: Pattern[];
exclude?: ExcludeFunction;
}
```
#### Description
These are the props that are passed into the `commentTemplate` function.
**content**: `string`
This is the content to transform and is required.
**variables**: `CommentTemplateVariables`
Pass variables to the template which replace the content.
If a function is provided it is called with the current value, which can be `undefined`. Variables must be a flat object structure and cannot contain nested objects.
There is currently no support for nesting.
**throwIfMissingVariable**: _(optional)_ `boolean`
Throw an error if a variable is not found. This can be useful for making sure out of date comments don't clutter up your markdown and Typescript files.
**patterns**: _(optional)_ `Pattern[]`
The comment patterns to match for the provided content. You can limit the kind of comments that this function will transform.
- `html` will be able to transform markdown files with comments.
- `slash` will be able to transform languages with `slash star` comments like JavaScript and TypeScript.**exclude**: _(optional)_ `ExcludeFunction`
Return true when you want to exclude a match from being transformed.
#### Examples
**content**
The `content` can be pulled in from a file and then written back to the same file. All non-related content will be preserved.
```ts
import {
commentTemplate,
type CommentTemplateProps,
} from "https://deno.land/x/[email protected]/mod.ts";const props: CommentTemplateProps = {
content: await Deno.readTextFile(
new URL("tests/fixtures/sample.md", import.meta.url),
),
variables: { name: "Deno" },
};const transformedContent = commentTemplate(props);
```**variables**
Here is an example of creating variables with both a function and a string.
```ts
import {
type CommentTemplateProps,
} from "https://deno.land/x/[email protected]/mod.ts";const props: CommentTemplateProps = {
content: await Deno.readTextFile(
new URL("tests/fixtures/sample.md", import.meta.url),
),
variables: {
simple: "a simple string",
complex: (value) => value ? `${value} is complex` : "seems undefined",
},
};
```**exclude**
The following example excludes a match based on the provided name.
```ts
import { CommentTemplateProps } from "https://deno.land/x/[email protected]/mod.ts";const props: CommentTemplateProps = {
content: "",
variables: {},
exclude: ({ name }) => name.startsWith("excluded"),
};
```### `extractTemplateValues`
```ts
declare function extractTemplateValues(
content: string,
): ReadonlyMap;
```
#### Description
Extract the snippets from the provided content.
This returns each named snippet in a map.
#### Examples
The following example extracts the snippets from the provided content.
```ts
import {
extractTemplateValues,
} from "https://deno.land/x/[email protected]/mod.ts";const content = await Deno.readTextFile("./mod.d.md");
const variables = extractTemplateValues(content);
// => ReadonlyMap
```