-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a2da01d
commit efe156b
Showing
7 changed files
with
258 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Plugin } from "@engine/components/plugin.ts"; | ||
|
||
console.log(await Plugin.run({ | ||
context: { | ||
id: "introduction", | ||
entity: "user", | ||
handle: "octocat", | ||
retries: {}, | ||
mock: true | ||
} | ||
})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,42 +3,39 @@ import hljs from "y/[email protected]/lib/core?pin=v133" | |
import * as YAML from "std/yaml/parse.ts" | ||
|
||
/** Language cache */ | ||
const cache = {empty:true} as unknown as Record<string, {ace_mode:string, extensions?:string[], interpreters?:string[]}> | ||
|
||
//ignore/only language | ||
//gitattributes | ||
//gitignore | ||
//filter file if needed | ||
export const cache = await load("languages.yml") as Record<string, {ace_mode:string, extensions?:string[], interpreters?:string[]}> | ||
|
||
/** Language guesser */ | ||
export async function language(filename:string, content:string, {gitattributes = ""} = {}) { | ||
|
||
// TODO(@lowlighter): to implement | ||
// deno-lint-ignore require-await | ||
export async function language(_filename:string, content:string, {gitattributes = ""} = {}) { | ||
/* | ||
load("vendor.yml") | ||
load("documentation.yml") | ||
load("vendor.yml") | ||
load("documentation.yml") | ||
*/ | ||
|
||
// deno-lint-ignore no-explicit-any | ||
const result = {} as any | ||
|
||
// Process gitattributes override | ||
if (gitattributes) { | ||
result.from = "gitattributes" | ||
} | ||
|
||
//gitattributes override | ||
// Process interpreter | ||
if (content.startsWith("#!/")) { | ||
const line = content.split("\n", 1)[0] | ||
// search for single interpreter | ||
const _line = content.split("\n", 1)[0] | ||
result.from = "shebang" | ||
} | ||
|
||
// | ||
if (true) { | ||
// search from .filenames | ||
// Search for specific filename | ||
// deno-lint-ignore no-constant-condition | ||
if (false) { | ||
result.from = "filename" | ||
} | ||
|
||
if (true) { | ||
// search from .extension | ||
// Search for specific extension | ||
// deno-lint-ignore no-constant-condition | ||
if (false) { | ||
result.from = "extension" | ||
} | ||
|
||
|
@@ -50,14 +47,9 @@ load("documentation.yml") | |
} | ||
} | ||
|
||
|
||
/** Highlight code */ | ||
export async function highlight(language:string, code:string) { | ||
// Resolve language name | ||
if (cache.empty) { | ||
Object.assign(cache, await load("languages.yml")) | ||
delete cache.empty | ||
} | ||
for (const [key, {ace_mode:mode, extensions = []}] of Object.entries(cache)) { | ||
const name = key.toLocaleLowerCase() | ||
if ((name === language.toLocaleLowerCase())||(extensions.find(extension => extension === `.${language}`))) { | ||
|
@@ -66,7 +58,7 @@ export async function highlight(language:string, code:string) { | |
} | ||
} | ||
|
||
// Load language | ||
// Load language highlighting syntax | ||
if (!hljs.listLanguages().includes(language)) { | ||
try { | ||
const module = await import(`y/[email protected]/lib/languages/${language}?pin=v133`) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Imports | ||
import rehypeStringify from "y/[email protected]" | ||
import remarkParse from "y/[email protected]" | ||
import remarkRehype from "y/[email protected]" | ||
import remarkGfm from "y/[email protected]" | ||
import { unified } from "y/[email protected]" | ||
import sanitizeHTML from "y/[email protected]" | ||
import {highlight} from "@engine/utils/language.ts" | ||
import { DOMParser } from "x/[email protected]/deno-dom-wasm.ts" | ||
import { Format } from "@engine/utils/format.ts" | ||
|
||
/** Markdown renderer (internal) */ | ||
const remark = unified() | ||
// deno-lint-ignore no-explicit-any | ||
.use(remarkParse as any) | ||
.use(remarkGfm) | ||
.use(remarkRehype) | ||
// deno-lint-ignore no-explicit-any | ||
.use(rehypeStringify as any) | ||
|
||
/** Render markdown */ | ||
export async function markdown(text: string, { sanitize = "svg" } = {}) { | ||
let {value:render} = await remark.process(text) | ||
switch (sanitize) { | ||
// SVG content | ||
case "svg": { | ||
const allowedTags = [ | ||
// Headers | ||
"h1", "h2", "h3", "h4", "h5", "h6", | ||
// Text | ||
"p", "strong", "em", "del", | ||
// Blockquotes | ||
"blockquote", | ||
// Code | ||
"pre", "code", | ||
// Links | ||
"a", | ||
// Images | ||
"img", | ||
// Tables | ||
"table", "thead", "tbody", "tfoot", "tr", "th", "td", | ||
// Lists | ||
"ul", "ol", "li", "input", | ||
// Horizontal rules | ||
"hr", | ||
// Line breaks | ||
"br", | ||
] | ||
const allowedAttributes = { | ||
"*": ["class"], | ||
input: ["type", "checked", "disabled"], | ||
img: ["src", "alt"], | ||
} | ||
render = sanitizeHTML(sanitizeHTML(`${render}`, { | ||
allowedTags, | ||
allowedAttributes, | ||
}), { | ||
allowedTags: ["span", ...allowedTags.filter(tag => !["input"].includes(tag))], | ||
allowedAttributes, | ||
transformTags:{ | ||
h1:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
h2:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
h3:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
h4:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
h5:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
h6:sanitizeHTML.simpleTransform("div", {class:"link"}), | ||
a:sanitizeHTML.simpleTransform("span", {class:"link"}), | ||
input(_, input) { | ||
return { | ||
tagName: "span", | ||
attribs: input.type === "checkbox" ? {class:`input checkbox ${'checked' in input ? "checked" : ""}`.trim()} : {} as Record<string, never>, | ||
} | ||
}, | ||
}, | ||
}) | ||
} | ||
} | ||
|
||
// Code highlighting | ||
if (/<\/code>/.test(`${render}`)) { | ||
const document = new DOMParser().parseFromString(Format.html(`${render}`), "text/html")! | ||
await Promise.all([...document.querySelectorAll("code") as unknown as Array<{className:string, innerHTML:string}>].map(async (code) => { | ||
const language = code.className.replace("language-", "") | ||
if (language) { | ||
code.innerHTML = (await highlight(language, code.innerHTML)).code | ||
} | ||
})) | ||
render = document.querySelector("main")!.innerHTML | ||
} | ||
|
||
return render | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { expect, t } from "@engine/utils/testing.ts" | ||
import { markdown } from "@engine/utils/markdown.ts" | ||
|
||
Deno.test(t(import.meta, "`markdown()` returns processed html content"), { permissions: "none" }, async () => { | ||
await expect(markdown("**Hello**", {sanitize:"svg"})).to.eventually.equal("<p><strong>Hello</strong></p>") | ||
}) | ||
|
||
Deno.test(t(import.meta, "`markdown()` can highlight code blocks"), { permissions: "none" }, async () => { | ||
await expect(markdown("```ts\nconst foo = true\n```", {sanitize:"svg"})).to.eventually.match(/class="language-ts"/).and.to.match(/class="hljs-.*?"/) | ||
}) | ||
|
||
Deno.test(t(import.meta, "`markdown()` can handle task lists"), { permissions: "none" }, async () => { | ||
await expect(markdown("- [ ] A\n- [x] B", {sanitize:"svg"})).to.eventually.match(/class="input checkbox"/).and.to.match(/class="input checkbox checked"/) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters