Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow ] in filename code block #2169

Merged
merged 12 commits into from
Jul 24, 2023
2 changes: 1 addition & 1 deletion docs/content/2.get-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ The module automatically loads and parses them.

To render content pages, add a [catch-all route](https://nuxt.com/docs/guide/directory-structure/pages/#catch-all-route) using the `ContentDoc` component:

```vue [pages/[...slug].vue]
```vue [pages/[...slug\\].vue]
<template>
<main>
<ContentDoc />
Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.guide/2.displaying/1.rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The fetching endpoint defaults to the current route (`$route.path`). An explicit

Create a [catch all route](https://nuxt.com/docs/guide/directory-structure/pages/#catch-all-route) named `pages/[...slug].vue` and add the component:

```vue [pages/[...slug].vue]
```vue [pages/[...slug\\].vue]
<template>
<main>
<ContentDoc />
Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.api/1.components/1.content-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ The `empty`{lang=ts} slot can be used to display a default content before render

### Default

```html [pages/[...slug.vue]]
```html [pages/[...slug\\].vue]
<template>
<main>
<!-- Similar to <ContentDoc :path="$route.path" /> -->
Expand Down
6 changes: 3 additions & 3 deletions docs/content/4.api/1.components/2.content-renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Other types will currently be passed to default slot via `v-slot="{ data }"` or

The `default`{lang=ts} slot can be used to render the content via `v-slot="{ data }"` syntax.

```html [pages/[...slug.vue]]
```html [pages/[...slug\\].vue]
<script setup lang="ts">
const { data } = await useAsyncData('page-data', () => queryContent('/hello').findOne())
</script>
Expand All @@ -44,7 +44,7 @@ const { data } = await useAsyncData('page-data', () => queryContent('/hello').fi

The `empty`{lang=ts} slot can be used to display a default content when the document is empty:

```html [pages/[...slug.vue]]
```html [pages/[...slug\\].vue]
<script setup lang="ts">
const { data } = await useAsyncData('page-data', () => queryContent('/hello').findOne())
</script>
Expand All @@ -63,7 +63,7 @@ const { data } = await useAsyncData('page-data', () => queryContent('/hello').fi
::alert{type="info"}
Note that when you use default slot and `<ContentRendererMarkdown>` in your template you need to pass `components` to `<ContentRendererMarkdown>`.

```html [pages/[...slug].vue]
```html [pages/[...slug\\].vue]
<script setup lang="ts">
const { data } = await useAsyncData('page-data', () => queryContent('/hello').findOne())

Expand Down
4 changes: 2 additions & 2 deletions docs/content/4.api/1.components/4.content-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The `<ContentQuery>`{lang=html} component fetches a document and gives access to

The `default`{lang=ts} slot can be used to render the content via `v-slot="{ data }"`{lang=html} syntax.

```html [pages/[...slug.vue]]
```html [pages/[...slug\\].vue]
<!-- Similar to <ContentDoc :path="$route.path" /> -->
<template>
<main>
Expand All @@ -63,7 +63,7 @@ The `not-found`{lang=ts} slot can be used to display a default content before re
<template>
<main>
<ContentQuery path="/about/authors" :where="{ type: 'csv' }">
<template #default="{ data }">
<template #default="{ data }">
<ul>
<li v-for="author of data" :key="author.name">
{{ author.name }}
Expand Down
4 changes: 4 additions & 0 deletions docs/content/4.api/1.components/7.prose.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ Component properties will be:

Check out the [highlight options](/api/configuration#highlight) for more about the syntax highlighting.

::alert{type="warning"}
If you want to use `]` in the filename, you need to escape it with 2 backslashes: `\\]`. This is necessary since JS will automatically escape the backslash in a string so `\]` will be resolved as `]` breaking our regex.
farnabaz marked this conversation as resolved.
Show resolved Hide resolved
::

## `ProseCodeInline`

[:icon{name="fa-brands:github" class="inline -mt-1 w-6"} Source](https://github.com/nuxt/content/tree/main/src/runtime/components/Prose/ProseCodeInline.vue)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.api/2.composables/4.use-document-driven.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const {

Rendering the current page becomes a bliss with this composable:

```vue [pages/[...slug].vue]
```vue [pages/[...slug\\].vue]
<script setup lang="ts">
const { page } = useContent()
</script>
Expand Down
4 changes: 2 additions & 2 deletions docs/content/6.blog/1.announcing-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ authors:
- name: "Ahad Birang"
avatarUrl: https://pbs.twimg.com/profile_images/780374165136244736/x5HfdWA1_400x400.jpg
link: https://twitter.com/a_birang
- name: "ClΓ©ment Ollivier"
- name: "ClΓ©ment Ollivier"
avatarUrl: https://pbs.twimg.com/profile_images/1370286658432724996/ZMSDzzIi_400x400.jpg
link: https://twitter.com/clemcodes
tags:
Expand Down Expand Up @@ -63,7 +63,7 @@ https://content.nuxtjs.org

Create a `pages/[...slug].vue` file with the [`<ContentDoc>`](/guide/displaying/rendering) component inside:

```vue [pages/[...slug].vue]
```vue [pages/[...slug\\].vue]
<template>
<ContentDoc />
</template>
Expand Down
36 changes: 36 additions & 0 deletions playground/basic/components/content/ProseCode.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts" setup>
defineProps<{
code: string,
language?: string,
filename?: string,
highlights: number[],
meta?: string
}>()
</script>

<template>
<div v-if="language">
language <br>
{{ language }}
</div>
<div v-if="filename">
filename <br>
{{ filename }}
</div>
<div v-if="highlights">
highlights <br>
{{ highlights }}
</div>
<div v-if="meta">
meta <br>
{{ meta }}
</div>
<slot />
</template>

<style>
pre code .line {
display: block;
min-height: 1rem;
}
</style>
2 changes: 1 addition & 1 deletion playground/basic/content/1.real-content/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default defineNuxtConfig({

Render any document content.

```vue [pages/[...slug].vue]
```vue [pages/[...slug\\].vue]
<script setup>
const route = useRoute()
const { data } = await useAsyncData(`doc-${route.path}`, () => queryContent(route.path).findOne())
Expand Down
2 changes: 1 addition & 1 deletion playground/basic/content/2.features/3.mdc-highlighter.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: title
array:
- item
- itemKey: itemValue
object:
object:
name: object
version: 1
string: "string"
Expand Down
49 changes: 49 additions & 0 deletions playground/basic/content/2.features/8.custom-prose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
```vue [[...page\\].vue]{1} title="Custom Prose"
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```vue [[...page\\].vue] title="Custom Prose"
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```vue [[...page\\].vue]{1}
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```vue title="Custom Prose"
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```vue [file.js] {2-4}title="Custom Prose"
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```ts[[...page\\].vue] {4-6,7} other code block info
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
```[] {4-6,7} other code block info
<template>
<div>
<h1>Custom Prose</h1>
</div>
</template>
```
19 changes: 12 additions & 7 deletions src/runtime/markdown-parser/handler/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@ export function parseThematicBlock (lang: string) {
}
}

const language = lang.replace(/[{|[](.+)/, '').match(/^[^ \t]+(?=[ \t]|$)/)
const highlightTokens = lang.match(/{([^}]*)}/)
const filenameTokens = lang.match(/\[([^\]]*)\]/)
const meta = lang.replace(/^\w*\s*(\[[^\]]*\]|\{[^}]*\})?\s*(\[[^\]]*\]|\{[^}]*\})?\s*/, '')
const languageMatches = lang.replace(/[{|[](.+)/, '').match(/^[^ \t]+(?=[ \t]|$)/)
const highlightTokensMatches = lang.match(/{([^}]*)}/)
const filenameMatches = lang.match(/\[((\\]|[^\]])*)\]/)

const meta = lang
.replace(languageMatches?.[0] ?? '', '')
.replace(highlightTokensMatches?.[0] ?? '', '')
.replace(filenameMatches?.[0] ?? '', '')
.trim()
Comment on lines +25 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, it makes this part so much more readable! ❀️


return {
language: language ? language[0] : undefined,
highlights: parseHighlightedLines(highlightTokens && highlightTokens[1]),
filename: Array.isArray(filenameTokens) && filenameTokens[1] ? filenameTokens[1] : undefined,
language: languageMatches?.[0] || undefined,
highlights: parseHighlightedLines(highlightTokensMatches?.[1] || undefined),
Barbapapazes marked this conversation as resolved.
Show resolved Hide resolved
filename: filenameMatches?.[1].replace(/\\]/g, ']') || undefined,
meta
}
}
Expand Down