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

feat: line numbers support in magic-move #1619

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demo/starter/slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Powered by [shiki-magic-move](https://shiki-magic-move.netlify.app/), Slidev sup

Add multiple code blocks and wrap them with <code>````md magic-move</code> (four backticks) to enable the magic move. For example:

````md magic-move
````md magic-move {lines: true}
```ts {*|2|*}
// step 1
const author = reactive({
Expand Down
30 changes: 17 additions & 13 deletions docs/guide/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ function add(
```
````

You can enable line number to all slides by setting `lineNumbers: true` on the config or enable each code block individually by setting `lines: true`. You can also set the starting line for each code block and highlight the lines accordingly, defaults to 1:
To change the highlight in multiple clicks, you can use `|` to separate them:

````md
```ts {6,7}{lines:true,startLine:5}
```ts {2-3|5|all}
function add(
a: Ref<number> | number,
b: Ref<number> | number
Expand All @@ -138,10 +138,12 @@ function add(
```
````

To change the highlight in multiple clicks, you can use `|` to separate them:
This will first highlight `a: Ref<number> | number` and `b: Ref<number> | number`, and then `return computed(() => unref(a) + unref(b))` after one click, and lastly, the whole block.

You can set the line number to `hide` to hide the code block or `none` to not highlight any line:

````md
```ts {2-3|5|all}
```ts {hide|none}
function add(
a: Ref<number> | number,
b: Ref<number> | number
Expand All @@ -151,12 +153,16 @@ function add(
```
````

This will first highlight `a: Ref<number> | number` and `b: Ref<number> | number`, and then `return computed(() => unref(a) + unref(b))` after one click, and lastly, the whole block.
::: tip
Learn more in the [clicks animations guide](./animations#positioning).
:::

You can set the line number to `hide` to hide the code block or `none` to not highlight any line:
### Line Numbers

You can enable line number to all slides by setting `lineNumbers: true` on the config or enable each code block individually by setting `lines: true`. You can also set the starting line for each code block and highlight the lines accordingly, defaults to 1:

````md
```ts {hide|none}
```ts {6,7}{lines:true,startLine:5}
function add(
a: Ref<number> | number,
b: Ref<number> | number
Expand All @@ -166,9 +172,7 @@ function add(
```
````

::: tip
Learn more in the [clicks animations guide](./animations#positioning).
:::
### Max Height

If the code doesn't fit into one slide, you use the `maxHeight` to set a fixed height and enable scrolling:

Expand Down Expand Up @@ -240,10 +244,10 @@ console.log(`Step ${3}` as string)
````
`````

It's also possible to mix Magic Move with [line highlighting](#line-highlighting), for example:
It's also possible to mix Magic Move with [line highlighting](#line-highlighting) and [line numbers](#line-numbers), for example:

`````md
````md magic-move {at:4} // [!code hl]
````md magic-move {at:4, lines: true} // [!code hl]
```js {*|1|2-5} // [!code hl]
let count = 1
function add() {
Expand All @@ -253,7 +257,7 @@ function add() {

Non-code blocks in between as ignored, you can put some comments.

```js
```js {*}{lines: false} // [!code hl]
let count = 1
const add = () => count += 1
```
Expand Down
27 changes: 21 additions & 6 deletions packages/client/builtin/ShikiMagicMove.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
<script setup lang="ts">
import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
import type { KeyedTokensInfo } from 'shiki-magic-move/types'
import type { PropType } from 'vue'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import lz from 'lz-string'
import { useSlideContext } from '../context'
import { makeId, updateCodeHighlightRange } from '../logic/utils'
import { useNav } from '../composables/useNav'
import { CLICKS_MAX } from '../constants'
import { configs } from '../env'

const props = defineProps<{
at?: string | number
stepsLz: string
stepRanges: string[][]
}>()
const props = defineProps({
at: {
type: [String, Number],
default: '+1',
},
stepsLz: {
type: String,
required: true,
},
stepRanges: {
type: Array as PropType<string[][]>,
required: true,
},
lines: {
type: Boolean,
default: configs.lineNumbers,
},
})

const steps = JSON.parse(lz.decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
const { $clicksContext: clicks, $scale: scale, $zoom: zoom } = useSlideContext()
Expand All @@ -37,7 +52,7 @@ onMounted(() => {
throw new Error('[slidev] The length of stepRanges does not match the length of steps, this is an internal error.')

const clickCounts = ranges.value.map(s => s.length).reduce((a, b) => a + b, 0)
const clickInfo = clicks.calculateSince(props.at ?? '+1', clickCounts - 1)
const clickInfo = clicks.calculateSince(props.at, clickCounts - 1)
clicks.register(id, clickInfo)

watch(
Expand Down
19 changes: 14 additions & 5 deletions packages/slidev/node/syntax/transform/magic-move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ import { reCodeBlock } from './code-wrapper'
// eslint-disable-next-line regexp/no-useless-quantifier, regexp/no-super-linear-backtracking
const reMagicMoveBlock = /^````(?:md|markdown) magic-move(?: *(\{[^}]*\})?([^\n]*))?\n([\s\S]+?)^````$/gm

function parseLineNumbersOption(options: string) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure if this is the best way.

return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : undefined
}

/**
* Transform magic-move code blocks
*/
export function transformMagicMove(
shiki: Highlighter | undefined,
shikiOptions: MarkdownItShikiOptions | undefined,
configLineNumbers: boolean,
) {
return (ctx: MarkdownTransformContext) => {
ctx.s.replace(
Expand All @@ -28,12 +33,16 @@ export function transformMagicMove(
if (!matches.length)
throw new Error('Magic Move block must contain at least one code block')

const defaultLineNumbers = parseLineNumbersOption(options) ?? configLineNumbers

const ranges = matches.map(i => normalizeRangeStr(i[2]))
const steps = matches.map(i => codeToKeyedTokens(shiki, i[5].trimEnd(), {
...shikiOptions,
lang: i[1] as any,
}),
)
const steps = matches.map((i) => {
const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers
return codeToKeyedTokens(shiki, i[5].trimEnd(), {
...shikiOptions,
lang: i[1] as any,
}, lineNumbers)
})
const compressed = lz.compressToBase64(JSON.stringify(steps))
return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`
},
Expand Down
2 changes: 1 addition & 1 deletion packages/slidev/node/vite/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export function applyMarkdownTransform(
const transformers: (MarkdownTransformer | undefined)[] = [
transformSnippet,
ctx.options.data.config.highlighter
? transformMagicMove(shiki, shikiOptions)
? transformMagicMove(shiki, shikiOptions, ctx.options.data.config.lineNumbers)
: undefined,
transformMermaid,
transformPlantUml,
Expand Down
Loading