diff --git a/assets/javascripts/discourse/lib/rich-editor-extension.js b/assets/javascripts/discourse/lib/rich-editor-extension.js index d453ec1..8e2e936 100644 --- a/assets/javascripts/discourse/lib/rich-editor-extension.js +++ b/assets/javascripts/discourse/lib/rich-editor-extension.js @@ -188,17 +188,28 @@ function wrapInTag(state, node, tag) { state.closeBlock(node); } +// the cook writes a classless span holding a single declaration; anything +// looser is styling the browser inlined at copy time, not authored bbcode +function styledSpan(property, getAttrs) { + return { + tag: "span[style]:not([class])", + getAttrs: (dom) => { + const { style } = dom; + return style.length === 1 && style.item(0) === property + ? getAttrs(style.getPropertyValue(property)) + : false; + }, + }; +} + function colorMark(property) { return { attrs: { color: {} }, parseDOM: [ - { - style: property, - getAttrs: (value) => { - const color = normalizeColor(value); - return color ? { color } : false; - }, - }, + styledSpan(property, (value) => { + const color = normalizeColor(value); + return color ? { color } : false; + }), ], toDOM: (mark) => ["span", { style: `${property}:${mark.attrs.color}` }, 0], }; @@ -224,24 +235,19 @@ const extension = { bbcode_size: { attrs: { size: {} }, parseDOM: [ - { - style: "font-size", - getAttrs: (value) => - SIZE_VALUE.test(value) ? { size: parseInt(value, 10) } : false, - }, + styledSpan("font-size", (value) => + SIZE_VALUE.test(value) ? { size: parseInt(value, 10) } : false + ), ], toDOM: (mark) => ["span", { style: `font-size:${mark.attrs.size}%` }, 0], }, bbcode_font: { attrs: { font: {} }, parseDOM: [ - { - style: "font-family", - getAttrs: (value) => { - const font = unquoteFont(value); - return font ? { font } : false; - }, - }, + styledSpan("font-family", (value) => { + const font = unquoteFont(value); + return font ? { font } : false; + }), ], toDOM: (mark) => [ "span", @@ -256,7 +262,7 @@ const extension = { toDOM: () => ["span", { class: "highlight" }, 0], }, bbcode_small: { - parseDOM: [{ style: "font-size=x-small" }], + parseDOM: [styledSpan("font-size", (value) => value === "x-small" && {})], toDOM: () => ["span", { style: "font-size:x-small" }, 0], }, bbcode_aname: { diff --git a/test/javascripts/integration/rich-editor-extension-test.js b/test/javascripts/integration/rich-editor-extension-test.js index ab5c65e..e165a1e 100644 --- a/test/javascripts/integration/rich-editor-extension-test.js +++ b/test/javascripts/integration/rich-editor-extension-test.js @@ -279,6 +279,14 @@ module( '
stacked
', "stacked", ], + "pasted multi-declaration span html is not claimed": [ + 'calm
', + "calm", + ], + "pasted classed span html is not claimed": [ + 'calm
', + "calm", + ], "pasted generic font html is not claimed": [ 'mono
', "mono", diff --git a/test/javascripts/unit/lib/to-markdown-test.js b/test/javascripts/unit/lib/to-markdown-test.js new file mode 100644 index 0000000..123b0c2 --- /dev/null +++ b/test/javascripts/unit/lib/to-markdown-test.js @@ -0,0 +1,34 @@ +import { setupTest } from "ember-qunit"; +import { module, test } from "qunit"; +import { + registerRichEditorExtension, + resetRichEditorExtensions, +} from "discourse/lib/composer/rich-editor-extensions"; +import toMarkdown from "discourse/lib/to-markdown"; +import richEditorExtension from "discourse/plugins/discourse-bbcode/discourse/lib/rich-editor-extension"; + +module("discourse-bbcode | Unit | to-markdown", function (hooks) { + setupTest(hooks); + + hooks.beforeEach(async function () { + await resetRichEditorExtensions(); + registerRichEditorExtension(richEditorExtension); + }); + + // copying rendered content inlines theme colors onto the copied elements + test("ignores styles the browser inlined on copied content", async function (assert) { + assert.strictEqual( + await toMarkdown( + `@someonea command`
+ ),
+ "@someone `a command`"
+ );
+ });
+
+ test("keeps a cooked bbcode span", async function (assert) {
+ assert.strictEqual(
+ await toMarkdown(`red text`),
+ "[color=red]red[/color] text"
+ );
+ });
+});