FEATURE: Customizable rules and plugins for `PrettyText.markdown`.
This commit extends the options which can be passed to `PrettyText.markdown` so that which Markdown-it rules and Discourse Markdown plugins to be used when rendering a text can be customizable. Currently, this extension is mainly used by plugins.
This commit is contained in:
parent
9f5c8644d0
commit
c2afc3915b
|
@ -1493,6 +1493,45 @@ var bar = 'bar';
|
|||
);
|
||||
});
|
||||
|
||||
test("customizing markdown-it rules", function (assert) {
|
||||
assert.cookedOptions(
|
||||
"**bold**",
|
||||
{ markdownItRules: [] },
|
||||
"<p>**bold**</p>",
|
||||
"does not apply bold markdown when rule is not enabled"
|
||||
);
|
||||
|
||||
assert.cookedOptions(
|
||||
"**bold**",
|
||||
{ markdownItRules: ["emphasis"] },
|
||||
"<p><strong>bold</strong></p>",
|
||||
"applies bold markdown when rule is enabled"
|
||||
);
|
||||
});
|
||||
|
||||
test("features override", function (assert) {
|
||||
assert.cookedOptions(
|
||||
":grin: @sam",
|
||||
{ featuresOverride: [] },
|
||||
"<p>:grin: @sam</p>",
|
||||
"does not cook emojis when Discourse markdown engines are disabled"
|
||||
);
|
||||
|
||||
assert.cookedOptions(
|
||||
":grin: @sam",
|
||||
{ featuresOverride: ["emoji"] },
|
||||
'<p><img src="/images/emoji/google_classic/grin.png?v=10" title=":grin:" class="emoji" alt=":grin:"> @sam</p>',
|
||||
"cooks emojis when only the emoji markdown engine is enabled"
|
||||
);
|
||||
|
||||
assert.cookedOptions(
|
||||
":grin: @sam",
|
||||
{ featuresOverride: ["mentions", "text-post-process"] },
|
||||
`<p>:grin: <span class="mention">@sam</span></p>`,
|
||||
"cooks mentions when only the mentions markdown engine is enabled"
|
||||
);
|
||||
});
|
||||
|
||||
test("emoji", function (assert) {
|
||||
assert.cooked(
|
||||
":smile:",
|
||||
|
|
|
@ -353,6 +353,12 @@ export function setup(opts, siteSettings, state) {
|
|||
}
|
||||
});
|
||||
|
||||
if (opts.featuresOverride) {
|
||||
Object.keys(opts.features).forEach((feature) => {
|
||||
opts.features[feature] = opts.featuresOverride.includes(feature);
|
||||
});
|
||||
}
|
||||
|
||||
let copy = {};
|
||||
Object.keys(opts).forEach((entry) => {
|
||||
copy[entry] = opts[entry];
|
||||
|
@ -371,14 +377,22 @@ export function setup(opts, siteSettings, state) {
|
|||
enableDiffhtmlPreview: siteSettings.enable_diffhtml_preview,
|
||||
};
|
||||
|
||||
opts.engine = window.markdownit({
|
||||
const markdownitOpts = {
|
||||
discourse: opts.discourse,
|
||||
html: true,
|
||||
breaks: !siteSettings.traditional_markdown_linebreaks,
|
||||
xhtmlOut: false,
|
||||
linkify: siteSettings.enable_markdown_linkify,
|
||||
typographer: siteSettings.enable_markdown_typographer,
|
||||
});
|
||||
};
|
||||
|
||||
if (opts.discourse.markdownItRules !== undefined) {
|
||||
opts.engine = window
|
||||
.markdownit("zero", markdownitOpts) // Preset for "zero", https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js
|
||||
.enable(opts.discourse.markdownItRules);
|
||||
} else {
|
||||
opts.engine = window.markdownit(markdownitOpts);
|
||||
}
|
||||
|
||||
const quotation_marks = siteSettings.markdown_typographer_quotation_marks;
|
||||
if (quotation_marks) {
|
||||
|
|
|
@ -38,6 +38,8 @@ export function buildOptions(state) {
|
|||
customEmojiTranslation,
|
||||
watchedWordsReplace,
|
||||
watchedWordsLink,
|
||||
featuresOverride,
|
||||
markdownItRules,
|
||||
} = state;
|
||||
|
||||
let features = {};
|
||||
|
@ -76,6 +78,8 @@ export function buildOptions(state) {
|
|||
disableEmojis,
|
||||
watchedWordsReplace,
|
||||
watchedWordsLink,
|
||||
featuresOverride,
|
||||
markdownItRules,
|
||||
};
|
||||
|
||||
// note, this will mutate options due to the way the API is designed
|
||||
|
|
|
@ -156,6 +156,17 @@ module PrettyText
|
|||
end
|
||||
end
|
||||
|
||||
# Acceptable options:
|
||||
#
|
||||
# disable_emojis - Disables the emoji markdown engine.
|
||||
# features - A hash where the key is the markdown feature name and the value is a boolean to enable/disable the markdown feature.
|
||||
# The hash is merged into the default features set in pretty-text.js which can be used to add new features or disable existing features.
|
||||
# features_override - An array of markdown feature names to override the default markdown feature set. Currently used by plugins to customize what features should be enabled
|
||||
# when rendering markdown.
|
||||
# markdown_it_rules - An array of markdown rule names which will be applied to the markdown-it engine. Currently used by plugins to customize what markdown-it rules should be
|
||||
# enabled when rendering markdown.
|
||||
# topic_id - Topic id for the post being cooked.
|
||||
# user_id - User id for the post being cooked.
|
||||
def self.markdown(text, opts = {})
|
||||
# we use the exact same markdown converter as the client
|
||||
# TODO: use the same extensions on both client and server (in particular the template for mentions)
|
||||
|
@ -175,6 +186,8 @@ module PrettyText
|
|||
__paths = #{paths_json};
|
||||
__optInput.getURL = __getURL;
|
||||
#{"__optInput.features = #{opts[:features].to_json};" if opts[:features]}
|
||||
#{"__optInput.featuresOverride = #{opts[:features_override].to_json};" if opts[:features_override]}
|
||||
#{"__optInput.markdownItRules = #{opts[:markdown_it_rules].to_json};" if opts[:markdown_it_rules]}
|
||||
__optInput.getCurrentUser = __getCurrentUser;
|
||||
__optInput.lookupAvatar = __lookupAvatar;
|
||||
__optInput.lookupPrimaryUserGroup = __lookupPrimaryUserGroup;
|
||||
|
@ -190,8 +203,8 @@ module PrettyText
|
|||
__optInput.watchedWordsLink = #{WordWatcher.word_matcher_regexps(:link).to_json};
|
||||
JS
|
||||
|
||||
if opts[:topicId]
|
||||
buffer << "__optInput.topicId = #{opts[:topicId].to_i};\n"
|
||||
if opts[:topic_id]
|
||||
buffer << "__optInput.topicId = #{opts[:topic_id].to_i};\n"
|
||||
end
|
||||
|
||||
if opts[:user_id]
|
||||
|
@ -279,10 +292,6 @@ module PrettyText
|
|||
|
||||
def self.cook(text, opts = {})
|
||||
options = opts.dup
|
||||
|
||||
# we have a minor inconsistency
|
||||
options[:topicId] = opts[:topic_id]
|
||||
|
||||
working_text = text.dup
|
||||
|
||||
sanitized = markdown(working_text, options)
|
||||
|
|
|
@ -2072,4 +2072,32 @@ HTML
|
|||
|
||||
expect(cooked).to match_html(html)
|
||||
end
|
||||
|
||||
context "customizing markdown-it rules" do
|
||||
it 'customizes the markdown-it rules correctly' do
|
||||
cooked = PrettyText.cook('This is some text **bold**', markdown_it_rules: [])
|
||||
|
||||
expect(cooked).to eq("<p>This is some text **bold**</p>")
|
||||
|
||||
cooked = PrettyText.cook('This is some text **bold**', markdown_it_rules: ["emphasis"])
|
||||
|
||||
expect(cooked).to eq("<p>This is some text <strong>bold</strong></p>")
|
||||
end
|
||||
end
|
||||
|
||||
context "enabling/disabling features" do
|
||||
it "allows features to be overriden" do
|
||||
cooked = PrettyText.cook(':grin: @mention', features_override: [])
|
||||
|
||||
expect(cooked).to eq("<p>:grin: @mention</p>")
|
||||
|
||||
cooked = PrettyText.cook(':grin: @mention', features_override: ["emoji"])
|
||||
|
||||
expect(cooked).to eq("<p><img src=\"/images/emoji/twitter/grin.png?v=10\" title=\":grin:\" class=\"emoji\" alt=\":grin:\"> @mention</p>")
|
||||
|
||||
cooked = PrettyText.cook(':grin: @mention', features_override: ["mentions", "text-post-process"])
|
||||
|
||||
expect(cooked).to eq("<p>:grin: <span class=\"mention\">@mention</span></p>")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue