mirror of
https://github.com/h-sphere/sql-seal.git
synced 2026-07-22 10:10:28 +00:00
wip
This commit is contained in:
parent
3a1fcaccce
commit
0447368f53
9 changed files with 181 additions and 42 deletions
|
|
@ -4,4 +4,5 @@ export interface CellFunction<T = unknown> {
|
|||
get name(): string;
|
||||
get sqlFunctionArgumentsCount(): number;
|
||||
prepare(content: T): CellParserResult;
|
||||
renderAsString(content: T): string;
|
||||
}
|
||||
|
|
@ -40,6 +40,8 @@ export class ModernCellParser {
|
|||
}
|
||||
}
|
||||
|
||||
// If it is link string, use "a" renderer.
|
||||
|
||||
return content
|
||||
} catch (e) {
|
||||
console.error('Error parsing cell with data:', content, e)
|
||||
|
|
@ -64,6 +66,39 @@ export class ModernCellParser {
|
|||
}
|
||||
}
|
||||
|
||||
renderAsString(content: string) {
|
||||
try {
|
||||
if (!content) {
|
||||
return content
|
||||
}
|
||||
if (typeof content !== 'string') {
|
||||
return content
|
||||
}
|
||||
if (content.startsWith('SQLSEALCUSTOM')) {
|
||||
const parsedData = parse(content.slice('SQLSEALCUSTOM('.length, -1))
|
||||
const renderer = this.getRenderer(parsedData)
|
||||
return renderer!.renderAsString(parsedData.values)
|
||||
}
|
||||
|
||||
// FIXME: bring this one back
|
||||
// If it's an array, decode it and render each individual elements
|
||||
if (isStringifiedArray(content)) {
|
||||
try {
|
||||
const parsed: string[] = parse(content)
|
||||
return parsed.map(p => this.renderer)
|
||||
return renderStringifiedArray(content)
|
||||
} catch (e) {
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
return content
|
||||
} catch (e) {
|
||||
console.error('Error parsing cell with data:', content, e)
|
||||
return 'Parsing Error'
|
||||
}
|
||||
}
|
||||
|
||||
register(fn: CellFunction) {
|
||||
this.functions.set(fn.name, fn)
|
||||
}
|
||||
|
|
@ -77,8 +112,13 @@ export class ModernCellParser {
|
|||
}
|
||||
|
||||
private renderCustomElement(el: any) {
|
||||
const renderer = this.getRenderer(el)
|
||||
return renderer?.prepare(el.values)
|
||||
}
|
||||
|
||||
private getRenderer(el: any) {
|
||||
if (this.functions.has(el.type)) {
|
||||
return this.functions.get(el.type)!.prepare(el.values)
|
||||
return this.functions.get(el.type)!
|
||||
} else {
|
||||
throw new Error(`Custom function processor ${el.type} is not registered`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,16 @@ export class ParseResults {
|
|||
})
|
||||
}
|
||||
|
||||
renderAsString(data: Record<string, any>[], columns: string[]) {
|
||||
return data.map(d => {
|
||||
const res: Record<string, string> = {}
|
||||
for (const col of columns) {
|
||||
res[col] = this.cellParser.renderAsString(d[col])
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
initialise(parentEl: HTMLElement) {
|
||||
this.functions.forEach(fn => fn(parentEl))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,4 +90,19 @@ export class CheckboxParser implements CellFunction<Args> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderAsString(values: Args): string {
|
||||
if (!isCheckboxProp(values)) {
|
||||
if (!!values[0]) {
|
||||
return '[x]'
|
||||
}
|
||||
return '[ ]'
|
||||
} else {
|
||||
if (values.checked) {
|
||||
return '[x]'
|
||||
} else {
|
||||
return '[ ] '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,10 +17,7 @@ export class ImageParser implements CellFunction<Args> {
|
|||
return 2 // FIXME: should it be 1 or 2?
|
||||
}
|
||||
|
||||
prepare([href, path]: Args): CellParserResult {
|
||||
if (!isLinkLocal(href)) {
|
||||
return createEl('img', { attr: { src: href } });
|
||||
}
|
||||
getResourcePath(href: string, path?: string) {
|
||||
href = (href ?? '').trim()
|
||||
if (href.startsWith('![[')) {
|
||||
href = href.slice(3, -2)
|
||||
|
|
@ -35,8 +32,35 @@ export class ImageParser implements CellFunction<Args> {
|
|||
path = (path ? parentPath + '/' : '') + href
|
||||
const file = this.app.vault.getFileByPath(path);
|
||||
if (!file) {
|
||||
return 'File does not exist'
|
||||
throw new Error('File does not exist')
|
||||
}
|
||||
return this.create('img', { attr: { src: this.app.vault.getResourcePath(file) } });
|
||||
return this.app.vault.getResourcePath(file)
|
||||
}
|
||||
|
||||
prepare([href, path]: Args): CellParserResult {
|
||||
if (!isLinkLocal(href)) {
|
||||
return createEl('img', { attr: { src: href } });
|
||||
}
|
||||
try {
|
||||
let resourcePath = this.getResourcePath(href, path)
|
||||
return this.create('img', { attr: { src: resourcePath } });
|
||||
|
||||
} catch (e) {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
renderAsString([href, path]: Args): string {
|
||||
if (!isLinkLocal(href)) {
|
||||
return ``
|
||||
}
|
||||
|
||||
try {
|
||||
const resourcePath = this.getResourcePath(href, path)
|
||||
return `![[${resourcePath}]]`
|
||||
} catch (e) {
|
||||
return e.toString()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { CellFunction } from "../CellFunction";
|
|||
import { CellParserResult, Result } from "../ModernCellParser";
|
||||
import { App } from "obsidian";
|
||||
import { isLinkLocal, isLinktext, removeExtension } from "src/utils/ui/helperFunctions";
|
||||
import { parse } from 'json5'
|
||||
|
||||
type Args = [string] | [string, string]
|
||||
|
||||
|
|
@ -18,6 +19,44 @@ export class LinkParser implements CellFunction<Args> {
|
|||
return 2 // FIXME: should it be 1 or 2?
|
||||
}
|
||||
|
||||
parseLink(href: string, name?: string) {
|
||||
if (!name) {
|
||||
name = href
|
||||
}
|
||||
href = href.trim()
|
||||
let cls = ''
|
||||
if (isLinktext(href)) {
|
||||
const [path, linkName] = href.slice(2, -2).split('|')
|
||||
const link = this.app.metadataCache.getFirstLinkpathDest(path, '')
|
||||
|
||||
if (name.trim() === href) {
|
||||
name = linkName ?? path
|
||||
}
|
||||
|
||||
if (!link) {
|
||||
href = path
|
||||
} else {
|
||||
href = link.path
|
||||
}
|
||||
cls = 'internal-link'
|
||||
|
||||
} else if (isLinkLocal(href)) {
|
||||
let fileHref = href
|
||||
if (fileHref.endsWith('.md')) {
|
||||
fileHref = fileHref.slice(0, -3)
|
||||
}
|
||||
if (name === href) {
|
||||
const components = href.split('/')
|
||||
name = removeExtension(components[components.length - 1])
|
||||
}
|
||||
cls = 'internal-link'
|
||||
}
|
||||
|
||||
return {
|
||||
name, href, cls
|
||||
}
|
||||
}
|
||||
|
||||
prepare([href, name]: Args) {
|
||||
if (!href) {
|
||||
return ''
|
||||
|
|
@ -25,44 +64,47 @@ export class LinkParser implements CellFunction<Args> {
|
|||
|
||||
if (isStringifiedArray(href)) {
|
||||
try {
|
||||
// FIXME: this return should work differently
|
||||
renderStringifiedArray(href, href => this.prepare([href]))
|
||||
} catch (e) {
|
||||
return href
|
||||
}
|
||||
}
|
||||
const res = this.parseLink(href, name)
|
||||
const el = this.create('a', { text: res.name, href: res.href, cls: res.cls })
|
||||
return el
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = href
|
||||
renderAsString([href, name]: Args): string {
|
||||
if (!href) {
|
||||
return ''
|
||||
}
|
||||
href = href.trim()
|
||||
let cls = ''
|
||||
if (isLinktext(href)) {
|
||||
const [path, linkName] = href.slice(2, -2).split('|')
|
||||
const link = this.app.metadataCache.getFirstLinkpathDest(path, '')
|
||||
|
||||
if (name.trim() === href) {
|
||||
name = linkName ?? path
|
||||
}
|
||||
|
||||
if (!link) {
|
||||
href = path
|
||||
} else {
|
||||
href = link.path
|
||||
}
|
||||
cls = 'internal-link'
|
||||
|
||||
} else if (isLinkLocal(href)) {
|
||||
let fileHref = href
|
||||
if (fileHref.endsWith('.md')) {
|
||||
fileHref = fileHref.slice(0, -3)
|
||||
}
|
||||
if (name === href) {
|
||||
const components = href.split('/')
|
||||
name = removeExtension(components[components.length - 1])
|
||||
}
|
||||
cls = 'internal-link'
|
||||
// if (isStringifiedArray(href)) {
|
||||
// try {
|
||||
// // FIXME: parse and run render as strings
|
||||
// const arr: string[] = parse(href)
|
||||
|
||||
// return arr.map(e => this.renderAsString(e))
|
||||
|
||||
// const res = renderStringifiedArray(href, href => this.prepare([href]))
|
||||
// if (res instanceof HTMLElement) {
|
||||
// return res.outerHTML
|
||||
// }
|
||||
// return res
|
||||
// } catch (e) {
|
||||
// return href
|
||||
// }
|
||||
// }
|
||||
|
||||
const res = this.parseLink(href, name)
|
||||
if (res.cls == 'internal-link') {
|
||||
if (!name) {
|
||||
return `[[${res.href}]]`
|
||||
}
|
||||
const el = this.create('a', { text: name, href, cls })
|
||||
return el
|
||||
return `[[${res.href}|${res.name}]]`
|
||||
} else {
|
||||
return `[${res.name}](${res.href})`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ export default class SqlSealPlugin extends Plugin {
|
|||
|
||||
this.rendererRegistry.register('sql-seal-internal-table', new TableRenderer(this.app, this.cellParser))
|
||||
this.rendererRegistry.register('sql-seal-internal-grid', new GridRenderer(this.app, this, this.cellParser))
|
||||
this.rendererRegistry.register('sql-seal-internal-markdown', new MarkdownRenderer(this.app))
|
||||
this.rendererRegistry.register('sql-seal-internal-markdown', new MarkdownRenderer(this.app, this.cellParser))
|
||||
this.rendererRegistry.register('sql-seal-internal-list', new ListRenderer(this.app, this.cellParser))
|
||||
this.rendererRegistry.register('sql-seal-internal-template', new TemplateRenderer(this.app, this.cellParser))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { App } from "obsidian";
|
|||
import { RendererConfig } from "../renderer/rendererRegistry";
|
||||
import { displayError } from "../utils/ui";
|
||||
import { ViewDefinition } from "../grammar/parser";
|
||||
import { ParseResults } from "../cellParser/parseResults";
|
||||
import { ModernCellParser } from "../cellParser/ModernCellParser";
|
||||
|
||||
const mapDataFromHeaders = (columns: string[], data: Record<string, any>[]) => {
|
||||
return data.map(d => columns.map(c => String(d[c])))
|
||||
|
|
@ -11,7 +13,12 @@ const mapDataFromHeaders = (columns: string[], data: Record<string, any>[]) => {
|
|||
|
||||
export class MarkdownRenderer implements RendererConfig {
|
||||
|
||||
constructor(private readonly app: App) { }
|
||||
parseResult: ParseResults;
|
||||
|
||||
constructor(private readonly app: App, private readonly cellParser: ModernCellParser) {
|
||||
this.parseResult = new ParseResults(cellParser)
|
||||
|
||||
}
|
||||
|
||||
get rendererKey() {
|
||||
return 'markdown'
|
||||
|
|
@ -34,7 +41,7 @@ export class MarkdownRenderer implements RendererConfig {
|
|||
const tab = getMarkdownTable({
|
||||
table: {
|
||||
head: columns,
|
||||
body: mapDataFromHeaders(columns, data)
|
||||
body: mapDataFromHeaders(columns, this.parseResult.renderAsString(data, columns))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import { RendererConfig } from "./rendererRegistry";
|
|||
import { displayError } from "../utils/ui";
|
||||
import { ViewDefinition } from "../grammar/parser";
|
||||
import Handlebars from "handlebars";
|
||||
import { ParseResults } from "src/cellParser/parseResults";
|
||||
import { ModernCellParser } from "src/cellParser/ModernCellParser";
|
||||
import { ParseResults } from "../cellParser/parseResults";
|
||||
import { ModernCellParser } from "../cellParser/ModernCellParser";
|
||||
|
||||
interface TemplateRendererConfig {
|
||||
template: HandlebarsTemplateDelegate
|
||||
|
|
|
|||
Loading…
Reference in a new issue