asciidoctor.js
asciidoctor.js copied to clipboard
Implement File.mtime in a browser environment
I've opened an issue upstream: https://github.com/opal/opal/issues/1870 But I'm still not sure that we can return a reliable value and/or that this method make sense in a browser environment.
@mojavelinux Would you consider adding a special case in Asciidoctor core in https://github.com/asciidoctor/asciidoctor/blob/8c11ef85071c778f1d5428dc1bd841c47eea1b42/lib/asciidoctor.rb#L1326
Basically what we need to do is check that we are running in a browser environment (Opal) and return the current date.
Ref: #522
I'm happy to make an exception, but why would Asciidoctor.js be attempting to load a file in a browser environment in the first place? I would think that it can only use load with a string. I'm actually surprised this is the first place it fails.
I'm happy to make an exception, but why would Asciidoctor.js be attempting to load a file in a browser environment in the first place?
I guess that since the API is available, why not ? 😄 One use case could be an HTML page with an input text where you enter an URL to an AsciiDoc file and the JavaScript would to:
const html = asciidoctor.convertFile(url);
Arguably the user could load the content and then call the convert function or use this workaround:
const html = asciidoctor.convert('include::https://path.to/document.adoc');
But since most of the IO operations are implemented in a browser environment, I think we should handle this case.
Otherwise we should document that convertFile and loadFile are not available in a browser environment and return a better exception than mtime is not implemented.
I agree we could treat a URL as a file, but that requires much more than just a change to mtime. There are a lot of assumptions down the load/convert file path that the resource is, in fact, a file. So if/when we make this change, we need to think about it fully and not just do a quick hack. Right now, anything that is not filesystem based should be using load/convert.
Otherwise we should document that convertFile and loadFile are not available in a browser environment
I agree this is the right change in the shortterm. But it's not just "not available in a browser environment". It's more, when we say file, we mean a real filesystem path.
(because even Antora has to avoid loadFile because Antora is using a virtual file system).
So if/when we make this change, we need to think about it fully and not just do a quick hack. Right now, anything that is not filesystem based should be using load/convert.
Indeed I didn't think it through.
I agree we could treat a URL as a file, but that requires much more than just a change to mtime. There are a lot of assumptions down the load/convert file path that the resource is, in fact, a file.
Actually the following code is working in a browser environment if I implement mtime:
class File
def mtime
Time.now
end
end
const opts = {to_file: false};
const html = asciidoctor.convertFile('https://raw.githubusercontent.com/asciidoctor/asciidoctor.js/master/spec/fixtures/include.adoc', opts);
expect(html).to.include('include content');
Having said that, I still think that you are right. We need to think about it fully otherwise it will be fragile. I've experienced two issues during my experimentation:
- It's "mandatory" to use
to_file: false, otherwise an exception will be thrown since Asciidoctor will try to write a file (unlikely to succeed in a browser environment):TypeError: self.write_proc is not a function - If the safe mode is
safe, Asciidoctor will try to embed the default stylesheet but we don't know for sure where the file is located:IOError: Error reading file or directory: css/asciidoctor.css; reason: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'file:///path/to/document/css/asciidoctor.css'.
Hello, I'm working in Angular project and i want to générate html page from .adoc file,
but i'm stuck with this error, how can i fix it ?
core.js:6498 ERROR Error: Uncaught (in promise): mtime: asciidoctor: FAILED: <stdin>: Failed to load AsciiDoc document - undefined method `mtime' for #<File:0x4c0>
at resolvePromise (zone.js:1213)
at resolvePromise (zone.js:1167)
at zone.js:1279
at ZoneDelegate.invokeTask (zone.js:406)
at Object.onInvokeTask (core.js:28679)
at ZoneDelegate.invokeTask (zone.js:405)
at Zone.runTask (zone.js:178)
at drainMicroTaskQueue (zone.js:582)
at ZoneTask.invokeTask [as invoke] (zone.js:491)
at invokeTask (zone.js:1600)
my typescript class
import { Component, OnInit } from '@angular/core';
import Processor, { Asciidoctor } from 'asciidoctor';
import asciidoctorHtml5s from 'asciidoctor-html5s';
@Component({
selector: 'app-doc',
templateUrl: './doc.component.html',
styleUrls: ['./doc.component.scss']
})
export class DocComponent implements OnInit {
processor : Asciidoctor;
html5: string | Asciidoctor.Document;
constructor() {
this.processor = Processor();
// Register the HTML5s converter and supporting extension.
asciidoctorHtml5s.register()
// default option
const defaultOptions = {
safe: "safe",
backend: "html5s",
to_file: false,
attributes: ['showtitle']
}
this.html5 = this.processor.convertFile('./../../doc/index.adoc', defaultOptions)
}
ngOnInit(): void {
}
}
It depends on how you want to manage your AsciiDoc files. You can fetch the content of your file from your Angular application (client side) using fetch or XMLHttpRequest:
fetch('http://localhost:1234/doc/index.adoc')
.then(response => response.text())
.then(data => {
processor.convert(data, defaultOptions)
})
It might also be possible to import the file at build time and use convert with the file contents instead of convertFile.
You can join the community chat at https://asciidoctor.zulipchat.com/ to ask usage questions, someone in the community might provide a better answer.
thank @Mogztter
i do this and it's work
i convert adoc file in build time, and i load it in componant with http.get
doc.component.html
<div [innerHTML]="myExternalHTML"></div>
doc.component.ts
import { Component, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-doc',
templateUrl: './doc.component.html',
styleUrls: ['./doc.component.scss']
})
export class DocComponent implements OnInit {
myExternalHTML :any;
constructor(private http: HttpClient, private sanitizer: DomSanitizer) {
this.http.get('./../../assets/html/index.html', { responseType: 'text' })
.subscribe((response :any) => {
this.myExternalHTML = this.sanitizer.bypassSecurityTrustHtml(response);;
}, (error: any) => {
console.log('Error: ' + error);
});
}
ngOnInit(): void {
}
}
Hello, I'm working in Angular project and i want to générate html page from .adoc file,
but i'm stuck with this error, how can i fix it ?
core.js:6498 ERROR Error: Uncaught (in promise): mtime: asciidoctor: FAILED: <stdin>: Failed to load AsciiDoc document - undefined method `mtime' for #<File:0x4c0> at resolvePromise (zone.js:1213) at resolvePromise (zone.js:1167) at zone.js:1279 at ZoneDelegate.invokeTask (zone.js:406) at Object.onInvokeTask (core.js:28679) at ZoneDelegate.invokeTask (zone.js:405) at Zone.runTask (zone.js:178) at drainMicroTaskQueue (zone.js:582) at ZoneTask.invokeTask [as invoke] (zone.js:491) at invokeTask (zone.js:1600)my typescript class
import { Component, OnInit } from '@angular/core'; import Processor, { Asciidoctor } from 'asciidoctor'; import asciidoctorHtml5s from 'asciidoctor-html5s'; @Component({ selector: 'app-doc', templateUrl: './doc.component.html', styleUrls: ['./doc.component.scss'] }) export class DocComponent implements OnInit { processor : Asciidoctor; html5: string | Asciidoctor.Document; constructor() { this.processor = Processor(); // Register the HTML5s converter and supporting extension. asciidoctorHtml5s.register() // default option const defaultOptions = { safe: "safe", backend: "html5s", to_file: false, attributes: ['showtitle'] } this.html5 = this.processor.convertFile('./../../doc/index.adoc', defaultOptions) } ngOnInit(): void { } }