Skip to content

Commit

Permalink
fix(build): handle importing code snippets not having an extension (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
brc-dd authored Sep 16, 2023
1 parent f409e20 commit e99aaad
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 21 deletions.
44 changes: 43 additions & 1 deletion __tests__/unit/node/markdown/plugins/snippet.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
import { dedent } from 'node/markdown/plugins/snippet'
import { dedent, rawPathToToken } from 'node/markdown/plugins/snippet'

const removeEmptyKeys = <T extends Record<string, unknown>>(obj: T) => {
return Object.fromEntries(
Object.entries(obj).filter(([, value]) => value !== '')
) as T
}

/* prettier-ignore */
const rawPathTokenMap: [string, Partial<{ filepath: string, extension: string, title: string, region: string, lines: string, lang: string }>][] = [
['/path/to/file.extension', { filepath: '/path/to/file.extension', extension: 'extension', title: 'file.extension' }],
['./path/to/file.extension', { filepath: './path/to/file.extension', extension: 'extension', title: 'file.extension' }],
['/path to/file.extension', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension' }],
['./path to/file.extension', { filepath: './path to/file.extension', extension: 'extension', title: 'file.extension' }],
['/path.to/file.extension', { filepath: '/path.to/file.extension', extension: 'extension', title: 'file.extension' }],
['./path.to/file.extension', { filepath: './path.to/file.extension', extension: 'extension', title: 'file.extension' }],
['/path .to/file.extension', { filepath: '/path .to/file.extension', extension: 'extension', title: 'file.extension' }],
['./path .to/file.extension', { filepath: './path .to/file.extension', extension: 'extension', title: 'file.extension' }],
['/path/to/file', { filepath: '/path/to/file', title: 'file' }],
['./path/to/file', { filepath: './path/to/file', title: 'file' }],
['/path to/file', { filepath: '/path to/file', title: 'file' }],
['./path to/file', { filepath: './path to/file', title: 'file' }],
['/path.to/file', { filepath: '/path.to/file', title: 'file' }],
['./path.to/file', { filepath: './path.to/file', title: 'file' }],
['/path .to/file', { filepath: '/path .to/file', title: 'file' }],
['./path .to/file', { filepath: './path .to/file', title: 'file' }],
['/path/to/file.extension#region', { filepath: '/path/to/file.extension', extension: 'extension', title: 'file.extension', region: '#region' }],
['./path/to/file.extension {c#}', { filepath: './path/to/file.extension', extension: 'extension', title: 'file.extension', lang: 'c#' }],
['/path to/file.extension {1,2,4-6}', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension', lines: '1,2,4-6' }],
['/path to/file.extension {1,2,4-6 c#}', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension', lines: '1,2,4-6', lang: 'c#' }],
['/path.to/file.extension [title]', { filepath: '/path.to/file.extension', extension: 'extension', title: 'title' }],
['./path.to/file.extension#region {c#}', { filepath: './path.to/file.extension', extension: 'extension', title: 'file.extension', region: '#region', lang: 'c#' }],
['/path/to/file#region {1,2,4-6}', { filepath: '/path/to/file', title: 'file', region: '#region', lines: '1,2,4-6' }],
['./path/to/file#region {1,2,4-6 c#}', { filepath: './path/to/file', title: 'file', region: '#region', lines: '1,2,4-6', lang: 'c#' }],
['/path to/file {1,2,4-6 c#} [title]', { filepath: '/path to/file', title: 'title', lines: '1,2,4-6', lang: 'c#' }],
['./path to/file#region {1,2,4-6 c#} [title]', { filepath: './path to/file', title: 'title', region: '#region', lines: '1,2,4-6', lang: 'c#' }],
]

describe('node/markdown/plugins/snippet', () => {
describe('dedent', () => {
Expand Down Expand Up @@ -57,4 +93,10 @@ describe('node/markdown/plugins/snippet', () => {
`)
})
})

test('rawPathToToken', () => {
rawPathTokenMap.forEach(([rawPath, token]) => {
expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token)
})
})
})
51 changes: 31 additions & 20 deletions src/node/markdown/plugins/snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@ import type { RuleBlock } from 'markdown-it/lib/parser_block'
import path from 'path'
import type { MarkdownEnv } from '../../shared'

/**
* raw path format: "/path/to/file.extension#region {meta} [title]"
* where #region, {meta} and [title] are optional
* meta can be like '1,2,4-6 lang', 'lang' or '1,2,4-6'
* lang can contain special characters like C++, C#, F#, etc.
* path can be relative to the current file or absolute
* file extension is optional
* path can contain spaces and dots
*
* captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]']
*/
export const rawPathRegexp =
/^(.+?(?:(?:\.([a-z0-9]+))?))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/

export function rawPathToToken(rawPath: string) {
const [
filepath = '',
extension = '',
region = '',
lines = '',
lang = '',
rawTitle = ''
] = (rawPathRegexp.exec(rawPath) || []).slice(1)

const title = rawTitle || filepath.split('/').pop() || ''

return { filepath, extension, region, lines, lang, title }
}

export function dedent(text: string): string {
const lines = text.split('\n')

Expand Down Expand Up @@ -91,32 +120,14 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
const start = pos + 3
const end = state.skipSpacesBack(max, pos)

/**
* raw path format: "/path/to/file.extension#region {meta}"
* where #region and {meta} are optional
* and meta can be like '1,2,4-6 lang', 'lang' or '1,2,4-6'
*
* captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]']
*/
const rawPathRegexp =
/^(.+(?:\.([a-z0-9]+)))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/

const rawPath = state.src
.slice(start, end)
.trim()
.replace(/^@/, srcDir)
.trim()

const [
filepath = '',
extension = '',
region = '',
lines = '',
lang = '',
rawTitle = ''
] = (rawPathRegexp.exec(rawPath) || []).slice(1)

const title = rawTitle || filepath.split('/').pop() || ''
const { filepath, extension, region, lines, lang, title } =
rawPathToToken(rawPath)

state.line = startLine + 1

Expand Down

0 comments on commit e99aaad

Please sign in to comment.