Files
e9522fdd03 FEATURE: introduce a ProseMirror editor (#30815)
This is the first in a series of PRs to introduce a
ProseMirror-based
WYSIWYM editor experience
alongside our current textarea Markdown editor.

Behind a hidden site setting, this PR adds a toggle to the composer
toolbar, allowing users to switch between the two options.

Our implementation builds upon the excellent ProseMirror and its
non-core Markdown
module, using the
module's schema, parsing, and serialization definitions as the base for
further Discourse-specific features.

An extension API is included to enable further customizations.

The necessary extensions to support all Discourse's core and core
plugins features **will be implemented in subsequent PRs**.

---------

Co-authored-by: David Taylor <[email protected]>
2025-02-04 14:37:18 -03:00

65 lines
1.6 KiB
Plaintext

import { tracked } from "@glimmer/tracking";
import { click, render, settled, waitFor } from "@ember/test-helpers";
import DEditor from "discourse/components/d-editor";
export async function testMarkdown(
assert,
markdown,
expectedHtml,
expectedMarkdown
) {
const self = new (class {
@tracked value = markdown;
@tracked view;
})();
const handleSetup = (textManipulation) => {
self.view = textManipulation.view;
};
await render(<template>
<DEditor
@value={{self.value}}
@processPreview={{false}}
@onSetup={{handleSetup}}
/>
</template>);
await click(".composer-toggle-switch");
await waitFor(".ProseMirror");
await settled();
const editor = document.querySelector(".ProseMirror");
// typeIn for contentEditable isn't reliable, and is slower
const tr = self.view.state.tr;
// insert a paragraph to enforce serialization
tr.insert(
tr.doc.content.size,
self.view.state.schema.node(
"paragraph",
null,
self.view.state.schema.text("X")
)
);
// then delete it
tr.delete(tr.doc.content.size - 3, tr.doc.content.size);
self.view.dispatch(tr);
await settled();
const html = editor.innerHTML
// we don't care about some PM-specifics
.replace(' class="ProseMirror-selectednode"', "")
.replace('<img class="ProseMirror-separator" alt="">', "")
.replace('<br class="ProseMirror-trailingBreak">', "")
// or artifacts
.replace('class=""', "");
assert.strictEqual(html, expectedHtml, `HTML should match for "${markdown}"`);
assert.strictEqual(
self.value,
expectedMarkdown,
`Markdown should match for "${markdown}"`
);
}