Terrace/packages/js/core/src/document.ts
2022-11-13 09:50:23 -05:00

79 lines
1.9 KiB
TypeScript

import type { Reader } from './readers/reader'
import { createLineData, parseLine } from './parser'
type Document = {
ended: boolean,
clone: () => Document,
next: () => Promise<Document>
current: () => Document
line: () => string,
head: () => string,
tail: () => string,
content: (contentLevel: number, lines: string[]) => Promise<string>,
seek: (matchHead: string, contentLevel: number) => Promise<Document|false>
}
export function useDocument (reader: Reader, indent: string = ' '): Document {
let lineData = createLineData(null, indent)
const document = {
ended: false,
clone() {
return useDocument(reader.clone(), indent)
},
async next() {
lineData.line = await reader.next()
if (lineData.line === null) return true
else parseLine(lineData)
},
current() {
return document
},
line() {
return lineData.line?.slice(lineData.offsetHead)
},
head () {
return lineData.line?.slice(lineData.offsetHead, lineData.offsetTail)
},
tail () {
return lineData.line?.slice(lineData.offsetTail)
},
level () {
return lineData.level
},
async content (contentLevel = -1, lines: string[] = []): Promise<string> {
if (contentLevel === -1) contentLevel = lineData.level + 1
const ended = await document.next()
if (ended) return lines.join('\n')
if (lineData.level < contentLevel) return lines.join('\n')
lines.push(lineData.line?.slice(contentLevel) || '')
return document.content(contentLevel, lines)
},
async seek (matchHead: string, contentLevel = -1): Promise<Document|false> {
if (contentLevel === -1) contentLevel = lineData.level
const ended = await document.next()
if (ended) return false
if (document.head() === matchHead) return document
if (lineData.level < contentLevel) return false
return document.seek(matchHead, contentLevel)
}
}
return document
}