Scribble: Pre rendered HTML

Hi All,

I am working on pyffi a way to use Python libraries from Racket.
As an example I want to use Pygments as a showcase.
Pygments is a generic syntax highlighter and more than 500 languages are supported.
It would be great to use Pygments from within Scribble.

Currently, I can send a string of program text code to Pygments and get a
string containing html back. With the noclasses option the css styles are inline.

(pystring->string 
   (highlight code (PythonLexer) (HtmlFormatter #:noclasses #t)))

My problem is getting this string of html untouched through the html renderer of Scribble.

Looking around for solutions I found out I asked by the same think back in 2010 [1].
Matthew added cond-element to produce different output for different renderers as a result.

I also discovered that that Shririam uses sxml->element (by Danny Yoo) which converts html represented as sxml into a Scribble element. He uses it to embed YouTube videos and Google Forms in Scribble generated documents. The sxml here is written by hand.

There is an html to sxml parser in sxml, so I tried this:

(define (html->element x)
   (map sxml->element 
             (cdr (ssax:xml->sxml (open-input-string x) '()))))

It almost works. The problem is that the sxml eats spaces here and there.
The example below shows that the space between def and partition is missing.

This "solution" is fragile and even if it could be made to work -- I can't help thinking that I am crossing the river to fetch water [2].

Am I misssing a simple solution?

[1]
https://groups.google.com/g/racket-users/c/Ogp5tWcTCF4/m/kt8adVADCigJ

[2]
Danish idiom.

3 Likes

In case someone knows how to get the ssax:xml->sxml to preserve the spaces.

The issue is that a space between two spans is eaten.

<span style=\"color: #008000; font-weight: bold\">def</span>  <span style=\"color: #0000FF\">partition</span>

Here is all the html generated by Pygments.

"<div class=\"highlight\" style=\"background: #f8f8f8\"><pre style=\"line-height: 125%;\"><span></span><span style=\"color: #008000; font-weight: bold\">def</span>  <span style=\"color: #0000FF\">partition</span>(l, r, nums):\n<span style=\"color: #3D7B7B; font-style: italic\"># Last element will be the pivot and the first element the pointer</span>\npivot, ptr <span style=\"color: #666666\">=</span> nums[r], l\n<span style=\"color: #008000; font-weight: bold\">for</span> i <span style=\"color: #AA22FF; font-weight: bold\">in</span> <span style=\"color: #008000\">range</span>(l, r):\n    <span style=\"color: #008000; font-weight: bold\">if</span> nums[i] <span style=\"color: #666666\">&lt;=</span> pivot:\n        <span style=\"color: #3D7B7B; font-style: italic\"># Swapping values smaller than the pivot to the front</span>\n        nums[i], nums[ptr] <span style=\"color: #666666\">=</span> nums[ptr], nums[i]\n        ptr <span style=\"color: #666666\">+=</span> <span style=\"color: #666666\">1</span>\n<span style=\"color: #3D7B7B; font-style: italic\"># Finally swapping the last element with the pointer indexed number</span>\nnums[ptr], nums[r] <span style=\"color: #666666\">=</span> nums[r], nums[ptr]\n<span style=\"color: #008000; font-weight: bold\">return</span> ptr\n</pre></div>\n"

And here is the output from the parser:

'((div
   (@ (style "background: #f8f8f8") (class "highlight"))
   (pre
    (@ (style "line-height: 125%;"))
    (span)
    (span (@ (style "color: #008000; font-weight: bold")) "def")
    (span (@ (style "color: #0000FF")) "partition")
    "(l, r, nums):\n"
    (span
     (@ (style "color: #3D7B7B; font-style: italic"))
     "# Last element will be the pivot and the first element the pointer")
    "\npivot, ptr "
    (span (@ (style "color: #666666")) "=")
    " nums[r], l\n"
    (span (@ (style "color: #008000; font-weight: bold")) "for")
    " i "
    (span (@ (style "color: #AA22FF; font-weight: bold")) "in")
    (span (@ (style "color: #008000")) "range")
    "(l, r):\n    "
    (span (@ (style "color: #008000; font-weight: bold")) "if")
    " nums[i] "
    (span (@ (style "color: #666666")) "<=")
    " pivot:\n        "
    (span
     (@ (style "color: #3D7B7B; font-style: italic"))
     "# Swapping values smaller than the pivot to the front")
    "\n        nums[i], nums[ptr] "
    (span (@ (style "color: #666666")) "=")
    " nums[ptr], nums[i]\n        ptr "
    (span (@ (style "color: #666666")) "+=")
    (span (@ (style "color: #666666")) "1")
    (span
     (@ (style "color: #3D7B7B; font-style: italic"))
     "# Finally swapping the last element with the pointer indexed number")
    "\nnums[ptr], nums[r] "
    (span (@ (style "color: #666666")) "=")
    " nums[r], nums[ptr]\n"
    (span (@ (style "color: #008000; font-weight: bold")) "return")
    " ptr\n")))```

Using html-parsing instead of sxml does the trick.

(define (html->element x)
   (define top (cdr (html->xexp (open-input-string x))))
   (map sxml->element top))

Thanks to sorawee for the tip.

2 Likes

I use the scribble-minted library by William Bowman.

The compile fails here because pygmentize has not been installed.

1 Like

Thanks for the tip. I have looked at the code, but can't figure out how it converts the output from html to Scribble.

Looks like it just gets the raw HTML and shunts it into CDATA

2 Likes