Skip to content

Commit

Permalink
feat(vscode): add Slidev language server (#1743)
Browse files Browse the repository at this point in the history
Co-authored-by: _Kerman <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Anthony Fu <[email protected]>
Co-authored-by: Anthony Fu <[email protected]>
  • Loading branch information
5 people authored Jul 20, 2024
1 parent 6293e10 commit 73f5b4b
Show file tree
Hide file tree
Showing 34 changed files with 2,116 additions and 128 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ packages/create-app/template/pages
packages/create-app/template/slides.md
packages/create-app/template/snippets
packages/slidev/README.md
packages/vscode/syntaxes/codeblock-patch.json
slides-export.md
*slides-export.pptx
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
shamefully-hoist=true
ignore-workspace-root-check=true
strict-peer-dependencies=false
link-workspace-packages=true
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode"
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode",
"--folder-uri=${workspaceRoot}/packages/vscode/syntaxes"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
Expand Down
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,9 @@
"jsonc",
"yaml"
],
"vitest.disableWorkspaceWarning": true
"vitest.disableWorkspaceWarning": true,
"slidev.include": [
"**/slides.md",
"packages/vscode/syntax/slidev.example.md"
]
}
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default antfu(
'**/template.md',
'**/example.md',
'test/fixtures/markdown/**/*.md',
'packages/vscode/syntaxes/slidev.example.md',
],
},
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"shiki": "^1.10.2",
"simple-git-hooks": "^2.11.1",
"taze": "^0.14.2",
"ts-json-schema-generator": "^2.3.0",
"tsup": "^8.1.0",
"typescript": "^5.5.3",
"vite": "^5.3.3",
Expand Down
6 changes: 4 additions & 2 deletions packages/parser/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ export function getDefaultConfig(): SlidevConfig {
css: 'unocss',
presenter: true,
htmlAttrs: {},
transition: undefined,
transition: null,
editor: true,
contextMenu: undefined,
contextMenu: null,
wakeLock: true,
remote: false,
mdc: false,
}
}

Expand Down
88 changes: 81 additions & 7 deletions packages/parser/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import YAML from 'yaml'
import { ensurePrefix } from '@antfu/utils'
import type { FrontmatterStyle, SlidevDetectedFeatures, SlidevMarkdown, SlidevPreparserExtension, SourceSlideInfo } from '@slidev/types'

export interface SlidevParserOptions {
noParseYAML?: boolean
preserveCR?: boolean
}

export function stringify(data: SlidevMarkdown) {
return `${data.slides.map(stringifySlide).join('\n').trim()}\n`
}
Expand Down Expand Up @@ -30,7 +35,7 @@ export function prettify(data: SlidevMarkdown) {
return data
}

function matter(code: string) {
function matter(code: string, options: SlidevParserOptions) {
let type: FrontmatterStyle | undefined
let raw: string | undefined

Expand All @@ -50,13 +55,13 @@ function matter(code: string) {
})
}

const doc = YAML.parseDocument(raw || '')
const doc = raw && !options.noParseYAML ? YAML.parseDocument(raw) : undefined

return {
type,
raw,
doc,
data: doc.toJSON(),
data: doc?.toJSON(),
content,
}
}
Expand All @@ -70,8 +75,8 @@ export function detectFeatures(code: string): SlidevDetectedFeatures {
}
}

export function parseSlide(raw: string): Omit<SourceSlideInfo, 'filepath' | 'index' | 'start' | 'contentStart' | 'end'> {
const matterResult = matter(raw)
export function parseSlide(raw: string, options: SlidevParserOptions = {}): Omit<SourceSlideInfo, 'filepath' | 'index' | 'start' | 'contentStart' | 'end'> {
const matterResult = matter(raw, options)
let note: string | undefined
const frontmatter = matterResult.data || {}
let content = matterResult.content.trim()
Expand Down Expand Up @@ -115,8 +120,9 @@ export async function parse(
markdown: string,
filepath: string,
extensions?: SlidevPreparserExtension[],
options: SlidevParserOptions = {},
): Promise<SlidevMarkdown> {
const lines = markdown.split(/\r?\n/g)
const lines = markdown.split(options.preserveCR ? '\n' : /\r?\n/g)
const slides: SourceSlideInfo[] = []

let start = 0
Expand All @@ -127,7 +133,7 @@ export async function parse(
return
const raw = lines.slice(start, end).join('\n')
const slide: SourceSlideInfo = {
...parseSlide(raw),
...parseSlide(raw, options),
filepath,
index: slides.length,
start,
Expand Down Expand Up @@ -195,6 +201,74 @@ export async function parse(
}
}

export function parseSync(
markdown: string,
filepath: string,
options: SlidevParserOptions = {},
): SlidevMarkdown {
const lines = markdown.split(options.preserveCR ? '\n' : /\r?\n/g)
const slides: SourceSlideInfo[] = []

let start = 0
let contentStart = 0

function slice(end: number) {
if (start === end)
return
const raw = lines.slice(start, end).join('\n')
const slide: SourceSlideInfo = {
...parseSlide(raw, options),
filepath,
index: slides.length,
start,
contentStart,
end,
}
slides.push(slide)
start = end + 1
contentStart = end + 1
}

for (let i = 0; i < lines.length; i++) {
const line = lines[i].trimEnd()
if (line.startsWith('---')) {
slice(i)

const next = lines[i + 1]
// found frontmatter, skip next dash
if (line[3] !== '-' && next?.trim()) {
start = i
for (i += 1; i < lines.length; i++) {
if (lines[i].trimEnd() === '---')
break
}
contentStart = i + 1
}
}
// skip code block
else if (line.trimStart().startsWith('```')) {
const codeBlockLevel = line.match(/^\s*`+/)![0]
let j = i + 1
for (; j < lines.length; j++) {
if (lines[j].startsWith(codeBlockLevel))
break
}
// Update i only when code block ends
if (j !== lines.length)
i = j
}
}

if (start <= lines.length - 1)
slice(lines.length)

return {
filepath,
raw: markdown,
slides,
}
}

function scanMonacoReferencedMods(md: string) {
const types = new Set<string>()
const deps = new Set<string>()
Expand Down
Loading

0 comments on commit 73f5b4b

Please sign in to comment.