Commit 2ce19d13 authored by Enrique Alcantara's avatar Enrique Alcantara

Code review feedback

- Use config instead of spec to describe
the parameters passed to the markdown
serializer
- Rename document variable to proseMirrorDocument
- Wrap document, dropCursor, gapCursor, and history
extensions
- Extract build_serializer_config into a different
service and add specs
parent 161a62e2
import Document from '@tiptap/extension-document';
export const tiptapExtension = Document;
import Dropcursor from '@tiptap/extension-dropcursor';
export const tiptapExtension = Dropcursor;
import Gapcursor from '@tiptap/extension-gapcursor';
export const tiptapExtension = Gapcursor;
import History from '@tiptap/extension-history';
export const tiptapExtension = History;
const buildSerializerConfig = (extensions = []) =>
extensions
.filter(({ serializer }) => serializer)
.reduce(
(serializers, { serializer, tiptapExtension: { name, type } }) => {
const collection = `${type}s`;
return {
...serializers,
[collection]: {
...serializers[collection],
[name]: serializer,
},
};
},
{
nodes: {},
marks: {},
},
);
export default buildSerializerConfig;
import Document from '@tiptap/extension-document';
import Dropcursor from '@tiptap/extension-dropcursor';
import Gapcursor from '@tiptap/extension-gapcursor';
import { Editor } from '@tiptap/vue-2'; import { Editor } from '@tiptap/vue-2';
import { isFunction } from 'lodash'; import { isFunction } from 'lodash';
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants'; import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
...@@ -9,8 +6,12 @@ import * as Bold from '../extensions/bold'; ...@@ -9,8 +6,12 @@ import * as Bold from '../extensions/bold';
import * as BulletList from '../extensions/bullet_list'; import * as BulletList from '../extensions/bullet_list';
import * as Code from '../extensions/code'; import * as Code from '../extensions/code';
import * as CodeBlockHighlight from '../extensions/code_block_highlight'; import * as CodeBlockHighlight from '../extensions/code_block_highlight';
import * as Document from '../extensions/document';
import * as Dropcursor from '../extensions/dropcursor';
import * as Gapcursor from '../extensions/gapcursor';
import * as HardBreak from '../extensions/hard_break'; import * as HardBreak from '../extensions/hard_break';
import * as Heading from '../extensions/heading'; import * as Heading from '../extensions/heading';
import * as History from '../extensions/history';
import * as HorizontalRule from '../extensions/horizontal_rule'; import * as HorizontalRule from '../extensions/horizontal_rule';
import * as Image from '../extensions/image'; import * as Image from '../extensions/image';
import * as Italic from '../extensions/italic'; import * as Italic from '../extensions/italic';
...@@ -19,6 +20,7 @@ import * as ListItem from '../extensions/list_item'; ...@@ -19,6 +20,7 @@ import * as ListItem from '../extensions/list_item';
import * as OrderedList from '../extensions/ordered_list'; import * as OrderedList from '../extensions/ordered_list';
import * as Paragraph from '../extensions/paragraph'; import * as Paragraph from '../extensions/paragraph';
import * as Text from '../extensions/text'; import * as Text from '../extensions/text';
import buildSerializerConfig from './build_serializer_config';
import { ContentEditor } from './content_editor'; import { ContentEditor } from './content_editor';
import createMarkdownSerializer from './markdown_serializer'; import createMarkdownSerializer from './markdown_serializer';
...@@ -28,12 +30,15 @@ const builtInContentEditorExtensions = [ ...@@ -28,12 +30,15 @@ const builtInContentEditorExtensions = [
BulletList, BulletList,
Code, Code,
CodeBlockHighlight, CodeBlockHighlight,
BulletList, Document,
Dropcursor,
Gapcursor,
HardBreak, HardBreak,
Heading, Heading,
History,
HorizontalRule, HorizontalRule,
Italic,
Image, Image,
Italic,
Link, Link,
ListItem, ListItem,
OrderedList, OrderedList,
...@@ -44,30 +49,9 @@ const builtInContentEditorExtensions = [ ...@@ -44,30 +49,9 @@ const builtInContentEditorExtensions = [
const collectTiptapExtensions = (extensions = []) => const collectTiptapExtensions = (extensions = []) =>
extensions.map(({ tiptapExtension }) => tiptapExtension); extensions.map(({ tiptapExtension }) => tiptapExtension);
const buildSerializerSpec = (extensions = []) =>
extensions
.filter(({ serializer }) => serializer)
.reduce(
(serializers, { serializer, tiptapExtension: { name, type } }) => {
const collection = `${type}s`;
return {
...serializers,
[collection]: {
...serializers[collection],
[name]: serializer,
},
};
},
{
nodes: {},
marks: {},
},
);
const createTiptapEditor = ({ extensions = [], ...options } = {}) => const createTiptapEditor = ({ extensions = [], ...options } = {}) =>
new Editor({ new Editor({
extensions: [Dropcursor, Gapcursor, History, Document, ...extensions], extensions: [...extensions],
editorProps: { editorProps: {
attributes: { attributes: {
class: 'gl-outline-0!', class: 'gl-outline-0!',
...@@ -84,8 +68,8 @@ export const createContentEditor = ({ renderMarkdown, extensions = [], tiptapOpt ...@@ -84,8 +68,8 @@ export const createContentEditor = ({ renderMarkdown, extensions = [], tiptapOpt
const allExtensions = [...builtInContentEditorExtensions, ...extensions]; const allExtensions = [...builtInContentEditorExtensions, ...extensions];
const tiptapExtensions = collectTiptapExtensions(allExtensions); const tiptapExtensions = collectTiptapExtensions(allExtensions);
const tiptapEditor = createTiptapEditor({ extensions: tiptapExtensions, ...tiptapOptions }); const tiptapEditor = createTiptapEditor({ extensions: tiptapExtensions, ...tiptapOptions });
const serializerSpec = buildSerializerSpec(allExtensions); const serializerConfig = buildSerializerConfig(allExtensions);
const serializer = createMarkdownSerializer({ render: renderMarkdown, serializerSpec }); const serializer = createMarkdownSerializer({ render: renderMarkdown, serializerConfig });
return new ContentEditor({ tiptapEditor, serializer }); return new ContentEditor({ tiptapEditor, serializer });
}; };
...@@ -15,7 +15,7 @@ const wrapHtmlPayload = (payload) => `<div>${payload}</div>`; ...@@ -15,7 +15,7 @@ const wrapHtmlPayload = (payload) => `<div>${payload}</div>`;
* that parses the Markdown and converts it into HTML. * that parses the Markdown and converts it into HTML.
* @returns a markdown serializer * @returns a markdown serializer
*/ */
export default ({ render = () => null, serializerSpec }) => ({ export default ({ render = () => null, serializerConfig }) => ({
/** /**
* Converts a Markdown string into a ProseMirror JSONDocument based * Converts a Markdown string into a ProseMirror JSONDocument based
* on a ProseMirror schema. * on a ProseMirror schema.
...@@ -49,11 +49,11 @@ export default ({ render = () => null, serializerSpec }) => ({ ...@@ -49,11 +49,11 @@ export default ({ render = () => null, serializerSpec }) => ({
* @returns A Markdown string * @returns A Markdown string
*/ */
serialize: ({ schema, content }) => { serialize: ({ schema, content }) => {
const document = schema.nodeFromJSON(content); const proseMirrorDocument = schema.nodeFromJSON(content);
const { nodes, marks } = serializerSpec; const { nodes, marks } = serializerConfig;
const serializer = new ProseMirrorMarkdownSerializer(nodes, marks); const serializer = new ProseMirrorMarkdownSerializer(nodes, marks);
return serializer.serialize(document, { return serializer.serialize(proseMirrorDocument, {
tightLists: true, tightLists: true,
}); });
}, },
......
import * as Blockquote from '~/content_editor/extensions/blockquote';
import * as Bold from '~/content_editor/extensions/bold';
import * as Dropcursor from '~/content_editor/extensions/dropcursor';
import * as Paragraph from '~/content_editor/extensions/paragraph';
import buildSerializerConfig from '~/content_editor/services/build_serializer_config';
describe('content_editor/services/build_serializer_config', () => {
describe('given one or more content editor extensions', () => {
it('creates a serializer config that collects all extension serializers by type', () => {
const extensions = [Bold, Blockquote, Paragraph];
const serializerConfig = buildSerializerConfig(extensions);
extensions.forEach(({ tiptapExtension, serializer }) => {
const { name, type } = tiptapExtension;
expect(serializerConfig[`${type}s`][name]).toBe(serializer);
});
});
});
describe('given an extension without serializer', () => {
it('does not include the extension in the serializer config', () => {
const serializerConfig = buildSerializerConfig([Dropcursor]);
expect(serializerConfig.marks[Dropcursor.tiptapExtension.name]).toBe(undefined);
expect(serializerConfig.nodes[Dropcursor.tiptapExtension.name]).toBe(undefined);
});
});
describe('given no extensions', () => {
it('creates an empty serializer config', () => {
expect(buildSerializerConfig()).toStrictEqual({
marks: {},
nodes: {},
});
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment