diff --git a/.changeset/smooth-news-try.md b/.changeset/smooth-news-try.md new file mode 100644 index 00000000..2c844385 --- /dev/null +++ b/.changeset/smooth-news-try.md @@ -0,0 +1,5 @@ +--- +"vocs": minor +--- + +Added "find and replace" syntax to the \`// [!include]\` marker (code snippets). diff --git a/site/pages/docs/guides/code-snippets.mdx b/site/pages/docs/guides/code-snippets.mdx index 72120368..fc66fae8 100644 --- a/site/pages/docs/guides/code-snippets.mdx +++ b/site/pages/docs/guides/code-snippets.mdx @@ -142,6 +142,48 @@ const block_$3 = await client.getBlock({ blockTag: 'latest' }) // [!code focus] // [!endregion usage-3] // [!code focus] ``` +## Find and Replace + +You can use `/(find)/(replace)/` syntax to find and replace text in the snippet. + +:::code-group + +````md [example.md] +```ts +import { writeFileSync } from 'node:fs' +//$ [!include ~/snippets/example.ts /viem/@viem\/core/ /mainnet/sepolia/] // [!code focus] + +writeFileSync('test.txt', blockNumber.toString()) +``` +```` + +```ts [docs/snippets/example.ts] +import { http, createPublicClient } from 'viem' +import { mainnet } from 'viem/chains' + +const client = createPublicClient({ + chain: mainnet, + transport: http(), +}) + +const blockNumber = await client.getBlockNumber() +``` + +::: + +Which will result in the snippet being rendered like this: + +```ts +import { writeFileSync } from 'node:fs' +// [!include ~/snippets/example.ts:import /viem/@viem\/core/ /mainnet/sepolia/ /http, createPublicClient/fk/] + +// [!include ~/snippets/example.ts:setup /mainnet/sepolia/] + +// [!include ~/snippets/example.ts:usage-1] + +writeFileSync('test.txt', blockNumber.toString()) +``` + ## Tip: Code Block Markers We can also include markers like [line highlight (`// [!code hl]`)](/docs/api/markdown#line-highlights) in our code snippets. diff --git a/src/vite/plugins/shikiji/transformerNotationInclude.ts b/src/vite/plugins/shikiji/transformerNotationInclude.ts index 16855bdf..efaea5c9 100644 --- a/src/vite/plugins/shikiji/transformerNotationInclude.ts +++ b/src/vite/plugins/shikiji/transformerNotationInclude.ts @@ -27,10 +27,15 @@ export const transformerNotationInclude = ({ const match = line.match(includeRegex) if (match) { const [, value] = match - const [fileName, region] = value.split(':') + const [file, ...query] = value.split(' ') + const [fileName, region] = file.split(':') const path = resolve(rootDir, fileName.replace('~', '.')) - const contents = readFileSync(path, { encoding: 'utf-8' }).replace(/\n$/, '') - lines.splice(i, 1, extractRegion(contents, region)) + + let contents = readFileSync(path, { encoding: 'utf-8' }).replace(/\n$/, '') + contents = extractRegion(contents, region) + contents = findAndReplace(contents, query) + + lines.splice(i, 1, contents) } i++ } @@ -66,3 +71,19 @@ function extractRegion(code: string, region: string | undefined) { return lines.join('\n') } + +const findAndReplaceRegex = /^\/(.*)([^\\])\/(.*)\/$/ + +function findAndReplace(code_: string, queries: string[]) { + if (queries.length === 0) return code_ + let code = code_ + for (const query of queries) { + const match = query.match(findAndReplaceRegex) + if (!match) return code + const [, find1, find2, replace1] = match + const find = (find1 + find2).replace('\\/', '/') + const replace = replace1.replace('\\/', '/') + code = code.replaceAll(find, replace) + } + return code +}