# ConTeXt, HTML source code side by side to the result from the web

I would like to write a document with some HTML code and next to it the result from a webpage.

Basically something like

\starthtmlexample
<strong>Hello</strong>, <em>world<em>
\stophtmlexample


Would print the code highlighted side by side to the result of how it looks in a website.

What I have in mind is that the environment

• creates a new file for each example with .html extension where it stores some code that goes before the contents of the environment;
• then the contents of the environment, in this case <strong>Hello</strong>, <em>world<em>;
• some post html tags to close the file;
• then process the file with a command

firefox -screenshot "screenshot-\n.png" "file:///Users/blah/blah/file-\n.html"


(well, with options --window-size="\certainwidth,\certainheight") to get a .png

• then add side by side the code (colored with \usemodule[vim]) and the image of the results.

Here's a “mockup”

\starttext

Something like

\starthtmlexample
<strong>Hello</strong>, <em>world<em>
\stophtmlexample

should do something like

%             here v pre code
\startbuffer
<html>
<strong>Hello</strong>, <em>world<em>
</html>
\stopbuffer % here ^ post code

% save this buffer to a file, say, htmls/html-1.html
% take a screenshot and save to screenshots/screenshot-1.png

\startxtable[option=stretch]
\startxrow
\startxcell
\typehtmlfile[htmls/html-1.html] % this seems buggy
\stopxcell
\startxcell
\externalfile[screenshots/screenshot-1.png]
\stopxcell
\stopxrow
\stopxtable

\stoptext


And to be clear, I'm relatively new to ConTeXt, so this might be solvable with other systems, and this is an X Y problem.

My idea is to write a document with many small examples of html code.

• Looks like a job for filter. – Henri Menke Nov 16 '18 at 20:38
• Thanks, yes, it looks like it :) Not able to make it work, but working on it. Nice to see this things exist. – Manuel Nov 16 '18 at 21:44

## 2 Answers

I cannot install webkit2png, so here is an illustration of how to do this using pandoc to convert html to pdf. First, let's start with the basic feature of showing both the source. Note that you need a local directory call html for this to work.

\usemodule[filter]

\startbuffer[before-html-example]
<html>
<head>
<meta charset="utf-8">
</head>
<body style="line-height: 1.5; font-size: 30">
\stopbuffer

\startbuffer[after-html-example]
</body>
</html>
\stopbuffer

\traceexternalfilters

\defineexternalfilter
[htmlexample]
[
directory=html,
bufferbefore=before-html-example,
bufferafter=after-html-example,
output=\externalfilterbasefile.pdf,
filtercommand={pandoc -f html \externalfilterinputfile\space -o \externalfilteroutputfile},
purge=no,
cache=yes,
readcommand=\DisplaySourceAndOutput,
]

\def\DisplaySourceAndOutput#1%
{\typefile{\externalfilterinputfile}
\externalfigure[#1][frame=on,width=10cm]}

\starttext
Hello
\starthtmlexample
<strong>Hello</strong>, <em>world<em>
\stophtmlexample
\stoptext


Now, let's add syntax highlighting and remove the before and after code from the displayed code snippet. So, we change the definition of \DisplaySourceAndOutput as follows:

\usemodule[vim]

\definevimtyping[html][syntax=html,directory=html]

\def\DisplaySourceAndOutput#1%
{\typehtmlfile[start=6,stop=-2]{\externalfilterinputfile}
\externalfigure[#1][frame=on,width=10cm]}


The value start=6 asks typehtmlfile to show the output from the 6th line (because before-html-example has 5 lines). The value stop=-2 asks not to show the last 2 lines (because after-html-example has 2 lines).

The above example now gives:

Now all you need to do is modify \DisplaySourceAndOutput as you want it to be displayed.

## EDIT

I don't understand what you mean by the comment:

For example to allow for \starthtmlexample ... \realhtmlexample ... \stophtmlexample or something like that.

Assuming that you want to ignore part of the environment, that is actually relatively easy (if you use buffers). For example, here is code to delete everything before the string !!START!! in the buffer:

\startluacode
filterdata = filterdata or {}

local ctxcatcodes  = catcodes.numbers.ctxcatcodes

filterdata.pre_process = function(name)
local content = buffers.getcontent(name)
content = string.gsub(content,'^.*!!START!!',"")
buffers.assign(name,content, ctxcatcodes)
end
\stopluacode

\starttext
Hello
\startbuffer[demo]
Stuff which is ignored
!!START!!
Stuff which is not ignored
\stopbuffer

\ctxlua{filterdata.pre_process("demo")}

\typebuffer[demo]

\stoptext

• Okey, right now this works. Still it would be nice if there was a way to pre-process the buffer contents inside tex before exporting and processing with the filtercommand. For example to allow for \starthtmlexample ... \realhtmlexample ... \stophtmlexample or something like that. Also, is there a way to output the contents of the code like in a table, with some cell for the text and then a second cell in the same row to put the image? – Manuel Nov 18 '18 at 21:52
• xtable does not work inside a macro. You can try the simpler \placesidebyside{...}{...} or natural tables. If you really need the features of xtables, then using \startsetups ... \stopsetups should probably work. – Aditya Nov 19 '18 at 4:34
• And how could I hook that lua code before filter saves the buffer to a file? Also I would love if I could have the same behaviour as strip=yes after that !!START!!. – Manuel Nov 19 '18 at 8:23
• Simply use \processhtmlexamplebuffer[demo]. – Aditya Nov 19 '18 at 13:49

This is an answer as a work-in-progress of what I'm trying to achieve, with the suggestion of Henri Menke of using filter module, in company with webkit2png.

At the moment this “just works”. But it's far from the definitive. I'll leave it here until (hopefully) someone writes a better and more complete answer.

Things that I hope I can change:

• save every extra file (from filter, vim, and webkit2png) in an folder/ so that the current directory is not polluted;
• This one is solved through some hacks in the bash commands.

have some “pre” and “post” code so one does not need to write everything (for example now I need to write <html><body> etc.), ideally the input would be for example

\starthtmlexample
<strong>Hello</strong>, <em>world</em>
\stophtmlexample

• manage correctly the sizes of the image, and the fonts, and everything. Right now it's very fragile (I've done by hand the adjust of font-size: 30 in the webpage).

• add some options to configure each example individually:

• for example if we want examples side by side (for small examples), something like \starthtmlexample[sidebyside] or \starthtmlexample[sidebyside=30] or something like that to say what part is for the code and which part for the image, and also another option to show first the code then below the result;
• options to change the pre-code, and post-code for an individual piece;
• some way of altering what's shown and what's written, for example

\starthmlexample
<p> Lorem ipsum ... </p>
\realhtml
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</p>
\stophtmlexample

• an inline way of doing this that ends up working in kind of tables:

\startxtable
\startxrow
\inlinehtmlexample{<b>bold</b>}
\stopxrow
\sartxrow
\inlinehtmlexample{<i>cursive</i>}
\stopxrow
\stopxtable


to align many small results one below another.

• right now I can't remember more things I thought (the frame=on is jut to know what's happening at the moment, that I don't actually know many things I'm using here); and of course

• get a decent base design so that it looks better than the default I wrote.

Here's the code:

\usemodule[vim]

\definevimtyping
[html]
[syntax=html,
directory=auxfiles,
before={\blank\setupbodyfont[small]},
after={\blank},
lines=split]

\startbuffer [before-html-example]
<html>
<head>
<meta charset="utf-8">
</head>
<body style="line-height: 1.5; font-size: 30">
\stopbuffer

\savebuffer [before-html-example] [before-html-example]

% \startbuffer [left-html-example]
%
% \stopbuffer
%
% \startbuffer [right-html-example]
%
% \stopbuffer

\startbuffer [after-html-example]
</body>
</html>
\stopbuffer

\savebuffer [after-html-example] [after-html-example]

\usemodule[filter]

\defineexternalfilter
[htmlexample]
[%directory=auxfiles, % this doesn't work as (I) expected
%  input=\externalfilterbasefile.html, % this doesn't exist, but may be should?
output=\externalfilterbasefile-full.png, % because of how webkit2png works
filtercommand=\htmlfiltercommand,
readcommand=\htmlexamplereadcommand,
cache=yes,
indentnext=no]

\def\htmlexamplereadcommand#1%
{\bpar\typehtmlfile{\externalfilterinputfile}\epar
\bpar\externalfigure[#1][frame=on,maxwidth=.5\textwidth]\epar}

\def\firefoxpath{/Applications/Firefox.app/Contents/MacOS}
\def\chromepath{/Applications/Google\ Chrome.app/Contents/MacOS}

\def\htmlfiltercommand
{\htmlconcatenateparts\htmlobtainpng}
\def\htmlconcatenateparts
{cat "html-before-html-example.tmp" "\externalfilterinputfile" "html-after-html-example.tmp" > "tmp.html";}
\def\htmlobtainpng
{webkit2png
%--dir="auxfiles" % doesn't work correctly with externalfilter
--fullsize
--width=1 % to get the minimum
--height=1 % to get the minimum
--scale=1 % unused
--filename="\externalfilterbasefile"
"tmp.html";}

% {\firefoxpath/firefox
%  -screenshot
%  "\externalfilteroutputfile"
%  "\externalfilterinputfile"}

% {\chromepath/Google\ Chrome
%  --headless
%  --screenshot="\externalfilteroutputfile"
%  "\externalfilterinputfile"}

\starttext

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

\starthtmlexample
<strong>Hello</strong>, <em>world</em>
\stophtmlexample

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

\starthtmlexample
<pre>
1   2   3   4   5   6   7   <b>Forever,</b><br/>
8   9  10  11  12  13  14      and ever.<br/>
15  16  17  18  19  20  21
</pre>
\stophtmlexample

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure \inlinehtml{<b>alo</b>} dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

\stopchapter

\stoptext

• For directory=output to work, you need to create the directory on your own. – Aditya Nov 18 '18 at 7:07
• For adding before and after content, search for bufferbefore and bufferafter in the documentation of the filter module – Aditya Nov 18 '18 at 7:13
• I see, still it doesn't work entirely well (or as expected) with webkit2png so I decided not to use it. And bufferbefore and bufferafter is of no use, because I want to input certain things, and then print those things while processing a different one. For now I think I could rely on bash commands, but I wrote this question in case someone showed a nice solution that is entirely ConTeXt / Lua, rather than hacks here and there. – Manuel Nov 18 '18 at 13:07
• Does webkit2png --filename=html/test.tmp html/test.png work from the command line? If so, then it should also work from within the filter module. Regarding bufferbeforr etc, I don't understand what you mean by print those things while processing a different one. Can you give an example? – Aditya Nov 18 '18 at 14:28
• I updated the answer. Well, the idea is to write in the example only a part of the whole file that is processed. So if I write \starthtmlexample <b>bold</bold> \stophtmlexample I want the file to be processed to have <html><body><b>bold</b></body></html> for example. – Manuel Nov 18 '18 at 14:56