# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import preserves, syndicate import ../schema/[assertions, config] {.passC: staticExec("pkg-config --cflags libxslt").} {.passL: staticExec("pkg-config --libs libxslt").} {.pragma: libxslt, header: "libxslt/xslt.h", importc.} type xmlDocPtr {.libxslt.} = distinct pointer xsltStylesheetPtr {.libxslt.} = distinct pointer proc xmlParseFile(filename: cstring): xmlDocPtr {.libxslt.} proc xmlFreeDoc(p: xmlDocPtr) {.libxslt.} proc xsltParseStylesheetFile(filename: cstring): xsltStylesheetPtr {.libxslt.} proc xsltApplyStylesheet( style: xsltStylesheetPtr, doc: xmlDocPtr, params: cstringArray): xmlDocPtr {.libxslt.} proc xsltFreeStylesheet(style: xsltStylesheetPtr) {.libxslt.} proc xsltSaveResultToString(txt: ptr pointer; len: ptr cint; res: xmlDocPtr; style: xsltStylesheetPtr): cint {.libxslt.} proc c_free*(p: pointer) {.importc: "free", header: "".} proc xsltSaveResultToString(res: xmlDocPtr; style: xsltStylesheetPtr): string = var txt: pointer len: cint if xsltSaveResultToString(addr txt, addr len, res, style) < 0: raise newException(CatchableError, "xsltSaveResultToString failed") if len > 0: result = newString(int len) copyMem(result[0].addr, txt, len) c_free(txt) proc initLibXml = discard proc spawnXsltActor*(turn: var Turn; root: Cap): Actor {.discardable.} = spawn("xslt", turn) do (turn: var Turn): initLibXml() during(turn, root, ?:XsltArguments) do (ds: Cap): let sheetsPat = ?Observe(pattern: !XsltTransform) ?? {0: grab(), 1: grab()} during(turn, ds, sheetsPat) do (stylesheet: Literal[string], input: Literal[string]): let cur = xsltParseStylesheetFile(stylesheet.value) doc = xmlParseFile(input.value) params = allocCStringArray([]) res = xsltApplyStylesheet(cur, doc, params) output = xsltSaveResultToString(res, cur) xmlFreeDoc(res) xmlFreeDoc(doc) deallocCStringArray(params) xsltFreeStylesheet(cur) publish(turn, ds, XsltTransform( stylesheet: stylesheet.value, input: input.value, output: output, )) when isMainModule: import syndicate/relays runActor("main") do (turn: var Turn; root: Cap): connectStdio(turn, root) spawnXsltActor(turn, root)