asciidoctor.js
asciidoctor.js copied to clipboard
Implement the content URI caching feature in a Node environment
Asciidoctor provides a built-in cache for content URI (based on open-uri-cached gem).
Currently, this feature is not available in Asciidoctor.js because the open-uri-cached is not transpile from Ruby to JavaScript.
I think it could be great to implement this feature in a Node environment. This feature will use the cache-uri attribute to enable the cache (similar to what Asciidoctor Ruby is doing: https://docs.asciidoctor.org/asciidoc/latest/directives/include-uri/#caching-uri-content)
To implement this feature, we could use: https://github.com/isaacs/node-lru-cache in order to set expiration time depending on response headers, configure a default max size, etc...
Asciidoctor core (Ruby) relies on https://github.com/tigris/open-uri-cached which cache content on disk. I don't like this approach since it creates "temporary" files in an arbitrary location (by default /tmp/open-uri-#{Process.uid}).
In addition, the library does not automatically clean/remove/invalidate cache. As a result, a long running process could lead to a disk saturation.
I think we should define a default cache size and use an in-memory cache. It might be interesting to configure a global cache or tie a cache to a document.
Interestingly, the cache is actually used between executions since the uid is stable (for instance, when running the CLI multiple times). It's also not possible to disable the cache in a program once enabled:
Asciidoctor.convert("image::http://localhost:5000/cc-zero.svg[opts=inline]", {
safe: 'safe',
attributes: {'allow-uri-read' => '', 'cache-uri' => ''}
})
Asciidoctor.convert("image::http://localhost:5000/cc-zero.svg[opts=inline]", {
safe: 'safe',
attributes: {'allow-uri-read' => ''}
})
The second call will use the cache despite the fact that cache-uri is absent. The reason is that open-uri/cache was loaded (and cannot or at least is not unloaded)
I think the URI/URL caching layer in Asciidoctor Ruby could be improved by making it pluggable. We integrated open-uri/cache in the early days to provide a quick win, but it's clearly a simple implementation.
I think the URI/URL caching layer in Asciidoctor Ruby could be improved by making it pluggable
An abstract layer on content read (file/URI) would be my dream ✨
We integrated open-uri/cache in the early days to provide a quick win, but it's clearly a simple implementation.
The most straightforward approach is to provide a JavaScript compatible implementation of open-uri/cache.
Opal cannot unload a module (or I least I don't know how) once loaded so the behavior is consistent with Asciidoctor Ruby.
I think I will store the cache in memory with a default value of 16Mb and use a simple implementation.