jirutka / asciidoctor-html5s

Semantic HTML5 converter (backend) for Asciidoctor
MIT License
89 stars 10 forks source link

Uninitialized converter using ES6 imports #2

Closed smolijar closed 6 years ago

smolijar commented 6 years ago

Using backend with import statements, causes the following output Object freezing is not supported by Opal followed by error:

    uninitialized constant Asciidoctor::Converter
      Converter: uninitialized constant Asciidoctor::Converter

This might be problem with all backends perhaps, first one I am using. Are backends in general usable for in browser usage with asciidoctor.js? I found no manual for backend usage.

Here is the change in my project that introduces the error: https://github.com/grissius/emily-editor/commit/5a223331b9ca488f0021a2bf003396594cda9e7b

jirutka commented 6 years ago

@Mogztter, do you have any idea what causes this problem?

ggrossetie commented 6 years ago

Not really... it looks like asciidoctor.js is not "loaded" because Opal should have initialized Asciidoctor::Converter.

I believe that this error is thrown when you import asciidoctor-html5s ?

I will try to reproduce this error in an integration test. You are using Babel to compile ES6 modules to commonJS, right ?

Please note that this warning can be safely ignored Object freezing is not supported by Opal.

ggrossetie commented 6 years ago

@grissius I found the root cause! Babel reorders the code. If you write:

import Asciidoctor from 'asciidoctor.js'
const asciidoctor = Asciidoctor();

import 'asciidoctor-html5s';

Babel will generate:

'use strict';

// import Asciidoctor from 'asciidoctor.js'
var _asciidoctor = require('asciidoctor.js');
var _asciidoctor2 = _interopRequireDefault(_asciidoctor);

// import 'asciidoctor-html5s';
require('asciidoctor-html5s');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// const asciidoctor = Asciidoctor();
var asciidoctor = (0, _asciidoctor2.default)();

As you can see const asciidoctor = Asciidoctor(); is now after import 'asciidoctor-html5s';. But the Asciidoctor context needs to be initialized before asciidoctor-html5s...

One way to fix this issue is to convert asciidoctor-html5s to a "lazy" module (ie. the module should not be loaded on import).

import Asciidoctor from 'asciidoctor.js'
import AsciidoctorHTML5Semantic from 'asciidoctor-html5s';

const asciidoctor = Asciidoctor();
AsciidoctorHTML5Semantic();

@jirutka What do you think ?

ggrossetie commented 6 years ago

Another way to do it, is to use the requirable compiler option: https://github.com/jirutka/asciidoctor-html5s/blob/49449af9371f862bd3ea2fdf088b449333dcab03/Rakefile#L31

And then to explicitly load the module:

require('asciidoctor.js')();
require('asciidoctor-html5s');
var Opal = require('opal-runtime');

Opal.load('asciidoctor-html5s');