Skip to content

Commit

Permalink
feat: line numbers support in magic-move (#1619)
Browse files Browse the repository at this point in the history
  • Loading branch information
kermanx authored May 28, 2024
1 parent 9b3beb4 commit f893705
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 26 deletions.
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) {
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

0 comments on commit f893705

Please sign in to comment.