|
| 1 | +import { resolve } from 'path' |
| 2 | +import { Plugin } from 'vite' |
| 3 | +import fs from 'fs-extra' |
| 4 | +import { isNotNull } from '@antfu/utils' |
| 5 | +import matter from 'gray-matter' |
| 6 | + |
| 7 | +const filepath = resolve(__dirname, '../slides.md') |
| 8 | + |
| 9 | +async function read() { |
| 10 | + return await fs.readFile(resolve(__dirname, '../slides.md'), 'utf-8') |
| 11 | +} |
| 12 | + |
| 13 | +function parse(raw: string) { |
| 14 | + const lines = raw.split(/\n/g) |
| 15 | + const pages: string[] = [] |
| 16 | + let start = 0 |
| 17 | + let dividers = 0 |
| 18 | + |
| 19 | + lines.forEach((line, i) => { |
| 20 | + if (line === '---') |
| 21 | + dividers += 1 |
| 22 | + |
| 23 | + if (dividers === 3) { |
| 24 | + pages.push(lines.slice(start, i).join('\n')) |
| 25 | + dividers = 1 |
| 26 | + start = i |
| 27 | + } |
| 28 | + }) |
| 29 | + |
| 30 | + if (start !== lines.length - 1) |
| 31 | + pages.push(lines.slice(start).join('\n')) |
| 32 | + |
| 33 | + return pages |
| 34 | +} |
| 35 | + |
| 36 | +export function createSlidesLoader(): Plugin { |
| 37 | + let raw: string | undefined |
| 38 | + let items: string[] = [] |
| 39 | + |
| 40 | + return { |
| 41 | + name: 'slides-loader', |
| 42 | + |
| 43 | + async configResolved() { |
| 44 | + raw = await read() |
| 45 | + items = parse(raw) |
| 46 | + }, |
| 47 | + |
| 48 | + async handleHotUpdate(ctx) { |
| 49 | + if (ctx.file === filepath) { |
| 50 | + raw = await ctx.read() |
| 51 | + items = parse(raw) |
| 52 | + |
| 53 | + return items |
| 54 | + .map((i, idx) => ctx.server.moduleGraph.getModuleById(`/@vite-slides/slides/${idx}.md`)) |
| 55 | + .filter(isNotNull) |
| 56 | + } |
| 57 | + }, |
| 58 | + |
| 59 | + resolveId(id) { |
| 60 | + if (id.startsWith('/@vite-slides/')) |
| 61 | + return id |
| 62 | + return null |
| 63 | + }, |
| 64 | + |
| 65 | + load(id) { |
| 66 | + const match = id.match(/^\/\@vite-slides\/slide\/(\d+).md$/) |
| 67 | + if (match) { |
| 68 | + const pageNo = parseInt(match[1]) |
| 69 | + return items[pageNo] |
| 70 | + } |
| 71 | + else if (id === '/@vite-slides/routes') { |
| 72 | + const imports: string[] = [] |
| 73 | + |
| 74 | + const routes = `export default [\n${ |
| 75 | + items |
| 76 | + .map((i, idx) => { |
| 77 | + imports.push(`import n${idx} from '/@vite-slides/slide/${idx}.md'`) |
| 78 | + const { data: meta } = matter(i) |
| 79 | + return `{ path: '/${idx}', name: 'page-${idx}', component: n${idx}, meta: ${JSON.stringify(meta)} },\n` |
| 80 | + }) |
| 81 | + .join('') |
| 82 | + }]` |
| 83 | + |
| 84 | + return [...imports, routes].join('\n') |
| 85 | + } |
| 86 | + }, |
| 87 | + } |
| 88 | +} |
0 commit comments