2021-06-30 23:48:27 +08:00
|
|
|
import { getAttributeOrThrow } from "../lib/attribute";
|
|
|
|
import { highlight } from "../cell/live_editor/monaco";
|
2021-07-29 01:35:36 +08:00
|
|
|
import { findChildOrThrow } from "../lib/utils";
|
2021-06-30 23:48:27 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A hook used to highlight source code in the root element.
|
|
|
|
*
|
|
|
|
* Configuration:
|
|
|
|
*
|
|
|
|
* * `data-language` - language of the source code
|
2021-07-29 01:35:36 +08:00
|
|
|
*
|
|
|
|
* The element should have two children:
|
|
|
|
*
|
|
|
|
* * one annotated with `data-source` attribute, it should contain
|
|
|
|
* the source code to be highlighted
|
|
|
|
*
|
|
|
|
* * one annotated with `data-target` where the highlighted code
|
|
|
|
* is rendered
|
2021-06-30 23:48:27 +08:00
|
|
|
*/
|
|
|
|
const Highlight = {
|
|
|
|
mounted() {
|
|
|
|
this.props = getProps(this);
|
2021-07-29 01:35:36 +08:00
|
|
|
this.state = {
|
|
|
|
sourceElement: null,
|
|
|
|
originalElement: null,
|
|
|
|
};
|
|
|
|
|
|
|
|
this.state.sourceElement = findChildOrThrow(this.el, "[data-source]");
|
|
|
|
this.state.targetElement = findChildOrThrow(this.el, "[data-target]");
|
2021-06-30 23:48:27 +08:00
|
|
|
|
2021-07-29 01:35:36 +08:00
|
|
|
highlightInto(
|
|
|
|
this.state.targetElement,
|
|
|
|
this.state.sourceElement,
|
|
|
|
this.props.language
|
|
|
|
).then(() => {
|
|
|
|
this.el.setAttribute("data-highlighted", "true");
|
|
|
|
});
|
2021-06-30 23:48:27 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
updated() {
|
|
|
|
this.props = getProps(this);
|
|
|
|
|
2021-07-29 01:35:36 +08:00
|
|
|
highlightInto(
|
|
|
|
this.state.targetElement,
|
|
|
|
this.state.sourceElement,
|
|
|
|
this.props.language
|
|
|
|
).then(() => {
|
|
|
|
this.el.setAttribute("data-highlighted", "true");
|
|
|
|
});
|
2021-06-30 23:48:27 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
function getProps(hook) {
|
|
|
|
return {
|
|
|
|
language: getAttributeOrThrow(hook.el, "data-language"),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-07-29 01:35:36 +08:00
|
|
|
function highlightInto(targetElement, sourceElement, language) {
|
|
|
|
const code = sourceElement.innerText;
|
2021-06-30 23:48:27 +08:00
|
|
|
|
2021-07-29 01:35:36 +08:00
|
|
|
return highlight(code, language).then((html) => {
|
|
|
|
targetElement.innerHTML = html;
|
2021-06-30 23:48:27 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Highlight;
|