asciidoctor / asciidoctor-extensions-lab

A lab for testing and demonstrating Asciidoctor extensions. Please do not use this code in production. If you want to use one of these extensions in your application, create a new project, import the code, and distribute it as a RubyGem. You can then request to make it a top-level project under the Asciidoctor organization.
Other
104 stars 101 forks source link

RunKit Code Block Processor #77

Closed thom4parisot closed 6 years ago

thom4parisot commented 7 years ago

RunKit is a tool to try Node.js in the browser. It is wired to Node package registry – npm.

capture d ecran 2017-03-05 a 19 17 33

I imagine something like this:

[source,javascript,runkit="nodeVersion:6"]
----
const lodash = require("lodash");

lodash.camelCase('get content');
----

becomes interactive as https://runkit.com/oncletom/58bc55b33cdd1a0013ae1a89 by pressing the Run in browser button (like the View Results extension).

<script src="https://embed.runkit.com"></script>
<script>
document.querySelectorAll('[data-runkit]').forEach(el => {
  RunKit.createNotebook({
    element: el,
    source: el.querySelector("code").textContent
  });
});
</script>

// ...

<pre class="javascript" data-runkit data-runkit-version="6"><code>
const lodash = require("lodash");

lodash.camelCase('get content');
</code></pre>

RunKit documentation is available here: https://runkit.com/docs/embed

cc @Mogztter

mojavelinux commented 7 years ago

Very cool!

I like the option to specify the implementation, though I think to make this more semantic we should use an option with a default implementation and allow the attribute to override that choice.

[source%interactive,javascript]
----
const lodash = require("lodash");

lodash.camelCase('get content');
----

(This builds on the semantics of %interactive option for checklists).

I'd also rename the runkit attribute to runner. That way, we have a consistent syntax if we add support for other languages.

We might also want to have a global attribute to set the runner(s).

mojavelinux commented 7 years ago

@hsablonniere You may be interested in where this is headed.

mojavelinux commented 7 years ago

Of course, how cool would it be to test some Asciidoctor.js in the browser as the main example that we show?

thom4parisot commented 7 years ago

Sure – we just need to be aware code snippets within a same document can be run by different runners. Authors could definitely mix Python and JS, each of them might have a different set of options depending on the runner runtime.

And indeed I almost hesitated writing the aforementioned snippets with asciidoctor-js to render some Asciidoc with Node in the browser ;-)

mojavelinux commented 7 years ago

we just need to be aware code snippets within a same document can be run by different runners.

Absolutely. I was thinking more along the lines of a runner per langauge. Something like:

:runner-javascript: nodeVersion:6
ggrossetie commented 7 years ago

When Asciidoctor encounters a delimited block or paragraph with an unrecognized name while parsing the document, it looks for a BlockProcessor registered to handle this name and, if found, invokes its {Processor#process} method to build a corresponding node in the document tree.

@mojavelinux Given this fact, what is the best approach to create an extension to process a source block ?

mojavelinux commented 7 years ago

The best option is a Treeprocessor. Technically, there's nothing wrong with that choice in this case since we want all the normal behavior of parsing a source block, we just want to do something else with it before conversion (aka rendering).

The BlockProcessor is intended for the case when you want to influence (actually take over) the parsing. (Technically, Asciidoctor Diagram could be done with a Treeprocessor too).

mojavelinux commented 7 years ago

In fact, I did something similar in one of the existing (somewhat poorly written) extensions in the lab. See https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/lib/shell-session-treeprocessor/extension.rb.

The drawback of treeprocessors right now find_by misses some blocks in the tree, including blocks inside AsciiDoc table cells...so you just have to work a bit harder to find all the blocks to process. For most documents, though, the blocks are accessible.

thom4parisot commented 6 years ago

It is out of scope of this repo so I close the issue.

I started working on it here: https://github.com/oncletom/asciidoctor-extension-interactive-runner.

mojavelinux commented 6 years ago

:+1:

ggrossetie commented 6 years ago

@oncletom The code looks really good, well done :+1: