import XNode from "@web-atoms/core/dist/core/XNode";
import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
import { ContentPage, isMobileView } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
import { UMD } from "@web-atoms/core/dist/core/types";
import WebApp from "@web-atoms/core/dist/web/WebApp";
import styled from "@web-atoms/core/dist/style/styled";
import AnimatedLoader from "../../controls/AnimatedLoader";
import Action from "@web-atoms/core/dist/view-model/Action";
(UMD as any).map("showdown", "https://cdn.jsdelivr.net/npm/showdown@1.9.0/");
const css = styled.css `
display: grid;
grid-template-columns: 1fr auto;
gap: 5px;
overflow: hidden;
& > .md {
overflow: auto;
align-self: stretch;
justify-self: stretch;
& pre {
border: solid 1px lightgray;
}
}
& > .index {
width: 200px;
align-self: stretch;
overflow: auto;
& > * {
margin: 5px;
cursor: pointer;
color: var(--link-color, blue);
&:hover {
text-decoration: underline;
}
}
}
`.installLocal();
let nextHeaderId = 1;
declare let System: any;
export default class MDPage extends ContentPage<{url: string; label: string;}> {
public index: HTMLDivElement;
public async init() {
this.title = this.parameters.label;
this.renderer = ;
const rs = await fetch( System.resolve(this.parameters.url));
const code = await rs.text();
if (rs.status > 300) {
this.renderer =
Failed to load {this.parameters.url}
{code}
;
return;
}
this.renderer = ;
this.index = this.element.querySelector(".index");
await this.loadCode(code);
}
@Action({ onEvent: "show-header"})
showHeader({ headerId }) {
const e = this.element.querySelector(`#${headerId}`);
e.scrollIntoView();
}
async loadCode(code: string) {
const app = this.app as WebApp;
app.installStyleSheet("https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css");
const showdown = await UMD.import("showdown/dist/showdown.js");
const text = code;
const converter = new showdown.Converter();
converter.setOption("openLinksInNewWindow",true);
converter.setOption("simplifiedAutoLink", true);
const element = this.element;
const mdRoot = element.querySelector(".md");
const md = document.createElement("div");
md.innerHTML = converter.makeHtml(text);
md.style.width = "100%";
md.style.height = "100%";
md.className = "page";
mdRoot.appendChild(md);
setTimeout(() => {
this.findHeader(md);
}, 100);
await UMD.import("https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/highlight.min.js");
const highlight = (window as any).hljs;
const all = document.querySelectorAll("pre > code");
// tslint:disable-next-line:prefer-for-of
for (let index = 0; index < all.length; index++) {
const e = all[index];
highlight.highlightBlock(e);
}
for(const iterator of Array.from(this.element.querySelectorAll("a"))) {
if(/^(http|https)\:\/\//) {
iterator.target = "_blank";
}
}
}
private findHeader(e: HTMLElement): void {
if (!e) {
return;
}
const all = Array.from(e.querySelectorAll("h1,h2,h3,h4,h5,h6"));
const index = this.index;
for (const iterator of all) {
const id = iterator.id ||= `nh-${nextHeaderId++}`;
const link = document.createElement("div");
link.className = "header"
link.textContent = iterator.textContent;
link.style.paddingLeft = `${parseFloat(iterator.tagName.substring(1)) * 5}px`;
link.setAttribute("data-click-event", "show-header");
link.setAttribute("data-header-id", id);
index.appendChild(link);
}
}
}