mirror of
https://github.com/discourse/discourse.git
synced 2024-12-21 10:38:14 +08:00
9a1695ccc1
With Embroider, we can rely on async `import()` to do the splitting for us. This commit extracts from `pretty-text` all the parts that are meant to be loaded async into a new `discourse-markdown-it` package that is also a V2 addon (meaning that all files are presumed unused until they are imported, aka "static"). Mostly I tried to keep the very discourse specific stuff (accessing site settings and loading plugin features) inside discourse proper, while the new package aims to have some resembalance of a general purpose library, a MarkdownIt++ if you will. It is far from perfect because of how all the "options" stuff work but I think it's a good start for more refactorings (clearing up the interfaces) to happen later. With this, pretty-text and app/lib/text are mostly a kitchen sink of loosely related text processing utilities. After the refactor, a lot more code related to setting up the engine are now loaded lazily, which should be a pretty nice win. I also noticed that we are currently pulling in the `xss` library at initial load to power the "sanitize" stuff, but I suspect with a similar refactoring effort those usages can be removed too. (See also #23790). This PR does not attempt to fix the sanitize issue, but I think it sets things up on the right trajectory for that to happen later. Co-authored-by: David Taylor <david@taylorhq.com>
75 lines
1.7 KiB
JavaScript
75 lines
1.7 KiB
JavaScript
import { cook as cookIt } from "./engine";
|
|
import DEFAULT_FEATURES from "./features";
|
|
import buildOptions from "./options";
|
|
import setup from "./setup";
|
|
|
|
function NOOP(ident) {
|
|
return ident;
|
|
}
|
|
|
|
export default class DiscourseMarkdownIt {
|
|
static withDefaultFeatures() {
|
|
return this.withFeatures(DEFAULT_FEATURES);
|
|
}
|
|
|
|
static withCustomFeatures(features) {
|
|
return this.withFeatures([...DEFAULT_FEATURES, ...features]);
|
|
}
|
|
|
|
static withFeatures(features) {
|
|
const withOptions = (options) => this.withOptions(features, options);
|
|
return { withOptions };
|
|
}
|
|
|
|
static withOptions(features, rawOptions) {
|
|
const { options, siteSettings, state } = buildOptions(rawOptions);
|
|
|
|
// note, this will mutate options due to the way the API is designed
|
|
// may need a refactor
|
|
setup(features, options, siteSettings, state);
|
|
|
|
return new DiscourseMarkdownIt(options);
|
|
}
|
|
|
|
static minimal() {
|
|
return this.withFeatures([]).withOptions({ siteSettings: {} });
|
|
}
|
|
|
|
constructor(options) {
|
|
if (!options.setup) {
|
|
throw new Error(
|
|
"Cannot construct DiscourseMarkdownIt from raw options, " +
|
|
"use DiscourseMarkdownIt.withOptions() instead"
|
|
);
|
|
}
|
|
|
|
this.options = options;
|
|
}
|
|
|
|
disableSanitizer() {
|
|
this.options.sanitizer = this.options.discourse.sanitizer = NOOP;
|
|
}
|
|
|
|
cook(raw) {
|
|
if (!raw || raw.length === 0) {
|
|
return "";
|
|
}
|
|
|
|
let result;
|
|
result = cookIt(raw, this.options);
|
|
return result ? result : "";
|
|
}
|
|
|
|
parse(markdown, env = {}) {
|
|
return this.options.engine.parse(markdown, env);
|
|
}
|
|
|
|
sanitize(html) {
|
|
return this.options.sanitizer(html).trim();
|
|
}
|
|
|
|
get linkify() {
|
|
return this.options.engine.linkify;
|
|
}
|
|
}
|