Commit 1bd45663 authored by Mark Florian's avatar Mark Florian

Merge branch '33603-js-part-refactor-audio-js' into 'master'

Part of #33603, Tech Debt - Combine Code in audio.js and video.js

See merge request gitlab-org/gitlab!18707
parents 2e324455 4886101c
// https://prosemirror.net/docs/ref/#model.ParseRule.priority
export const DEFAULT_PARSE_RULE_PRIORITY = 50;
export const HIGHER_PARSE_RULE_PRIORITY = 1 + DEFAULT_PARSE_RULE_PRIORITY;
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { Mark } from 'tiptap'; import { Mark } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown'; import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::MathFilter // Transforms generated HTML back to GFM for Banzai::Filter::MathFilter
export default class MathMark extends Mark { export default class MathMark extends Mark {
...@@ -15,7 +16,7 @@ export default class MathMark extends Mark { ...@@ -15,7 +16,7 @@ export default class MathMark extends Mark {
// Matches HTML generated by Banzai::Filter::MathFilter // Matches HTML generated by Banzai::Filter::MathFilter
{ {
tag: 'code.code.math[data-math-style=inline]', tag: 'code.code.math[data-math-style=inline]',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
}, },
// Matches HTML after being transformed by app/assets/javascripts/behaviors/markdown/render_math.js // Matches HTML after being transformed by app/assets/javascripts/behaviors/markdown/render_math.js
{ {
......
/* eslint-disable class-methods-use-this */ import Playable from './playable';
import { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
// Transforms generated HTML back to GFM for Banzai::Filter::AudioLinkFilter // Transforms generated HTML back to GFM for Banzai::Filter::AudioLinkFilter
export default class Audio extends Node { export default class Audio extends Playable {
get name() { constructor() {
return 'audio'; super();
} this.mediaType = 'audio';
get schema() {
return {
attrs: {
src: {},
alt: {
default: null,
},
},
group: 'block',
draggable: true,
parseDOM: [
{
tag: '.audio-container',
skip: true,
},
{
tag: '.audio-container p',
priority: 51,
ignore: true,
},
{
tag: 'audio[src]',
getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }),
},
],
toDOM: node => [
'audio',
{
src: node.attrs.src,
controls: true,
'data-setup': '{}',
'data-title': node.attrs.alt,
},
],
};
}
toMarkdown(state, node) {
defaultMarkdownSerializer.nodes.image(state, node);
state.closeBlock(node);
} }
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import { Image as BaseImage } from 'tiptap-extensions'; import { Image as BaseImage } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown'; import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { placeholderImage } from '~/lazy_loader'; import { placeholderImage } from '~/lazy_loader';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
export default class Image extends BaseImage { export default class Image extends BaseImage {
get schema() { get schema() {
...@@ -23,7 +24,7 @@ export default class Image extends BaseImage { ...@@ -23,7 +24,7 @@ export default class Image extends BaseImage {
// Matches HTML generated by Banzai::Filter::ImageLinkFilter // Matches HTML generated by Banzai::Filter::ImageLinkFilter
{ {
tag: 'a.no-attachment-icon', tag: 'a.no-attachment-icon',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
skip: true, skip: true,
}, },
// Matches HTML generated by Banzai::Filter::ImageLazyLoadFilter // Matches HTML generated by Banzai::Filter::ImageLazyLoadFilter
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import { Node } from 'tiptap'; import { Node } from 'tiptap';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter // Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
export default class OrderedTaskList extends Node { export default class OrderedTaskList extends Node {
...@@ -14,7 +15,7 @@ export default class OrderedTaskList extends Node { ...@@ -14,7 +15,7 @@ export default class OrderedTaskList extends Node {
content: '(task_list_item|list_item)+', content: '(task_list_item|list_item)+',
parseDOM: [ parseDOM: [
{ {
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
tag: 'ol.task-list', tag: 'ol.task-list',
}, },
], ],
......
/* eslint-disable class-methods-use-this */
/* eslint-disable @gitlab/i18n/no-non-i18n-strings */
import { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
/**
* Abstract base class for playable media, like video and audio.
* Must not be instantiated directly. Subclasses must set
* the `mediaType` property in their constructors.
* @abstract
*/
export default class Playable extends Node {
constructor() {
super();
this.mediaType = '';
this.extraElementAttrs = {};
}
get name() {
return this.mediaType;
}
get schema() {
const attrs = {
src: {},
alt: {
default: null,
},
};
const parseDOM = [
{
tag: `.${this.mediaType}-container`,
skip: true,
},
{
tag: `.${this.mediaType}-container p`,
priority: HIGHER_PARSE_RULE_PRIORITY,
ignore: true,
},
{
tag: `${this.mediaType}[src]`,
getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }),
},
];
const toDOM = node => [
this.mediaType,
{
src: node.attrs.src,
controls: true,
'data-setup': '{}',
'data-title': node.attrs.alt,
...this.extraElementAttrs,
},
];
return {
attrs,
group: 'block',
draggable: true,
parseDOM,
toDOM,
};
}
toMarkdown(state, node) {
defaultMarkdownSerializer.nodes.image(state, node);
state.closeBlock(node);
}
}
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import { Node } from 'tiptap'; import { Node } from 'tiptap';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::ReferenceFilter and subclasses // Transforms generated HTML back to GFM for Banzai::Filter::ReferenceFilter and subclasses
export default class Reference extends Node { export default class Reference extends Node {
...@@ -23,7 +24,7 @@ export default class Reference extends Node { ...@@ -23,7 +24,7 @@ export default class Reference extends Node {
parseDOM: [ parseDOM: [
{ {
tag: 'a.gfm:not([data-link=true])', tag: 'a.gfm:not([data-link=true])',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
getAttrs: el => ({ getAttrs: el => ({
className: el.className, className: el.className,
referenceType: el.dataset.referenceType, referenceType: el.dataset.referenceType,
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import TableRow from './table_row'; import TableRow from './table_row';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
const CENTER_ALIGN = 'center'; const CENTER_ALIGN = 'center';
...@@ -16,7 +17,7 @@ export default class TableHeaderRow extends TableRow { ...@@ -16,7 +17,7 @@ export default class TableHeaderRow extends TableRow {
parseDOM: [ parseDOM: [
{ {
tag: 'thead tr', tag: 'thead tr',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
}, },
], ],
toDOM: () => ['tr', 0], toDOM: () => ['tr', 0],
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { Node } from 'tiptap'; import { Node } from 'tiptap';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::TableOfContentsFilter // Transforms generated HTML back to GFM for Banzai::Filter::TableOfContentsFilter
export default class TableOfContents extends Node { export default class TableOfContents extends Node {
...@@ -16,11 +17,11 @@ export default class TableOfContents extends Node { ...@@ -16,11 +17,11 @@ export default class TableOfContents extends Node {
parseDOM: [ parseDOM: [
{ {
tag: 'ul.section-nav', tag: 'ul.section-nav',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
}, },
{ {
tag: 'p.table-of-contents', tag: 'p.table-of-contents',
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
}, },
], ],
toDOM: () => ['p', { class: 'table-of-contents' }, __('Table of Contents')], toDOM: () => ['p', { class: 'table-of-contents' }, __('Table of Contents')],
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import { Node } from 'tiptap'; import { Node } from 'tiptap';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter // Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
export default class TaskList extends Node { export default class TaskList extends Node {
...@@ -14,7 +15,7 @@ export default class TaskList extends Node { ...@@ -14,7 +15,7 @@ export default class TaskList extends Node {
content: '(task_list_item|list_item)+', content: '(task_list_item|list_item)+',
parseDOM: [ parseDOM: [
{ {
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
tag: 'ul.task-list', tag: 'ul.task-list',
}, },
], ],
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import { Node } from 'tiptap'; import { Node } from 'tiptap';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter // Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
export default class TaskListItem extends Node { export default class TaskListItem extends Node {
...@@ -20,7 +21,7 @@ export default class TaskListItem extends Node { ...@@ -20,7 +21,7 @@ export default class TaskListItem extends Node {
content: 'paragraph block*', content: 'paragraph block*',
parseDOM: [ parseDOM: [
{ {
priority: 51, priority: HIGHER_PARSE_RULE_PRIORITY,
tag: 'li.task-list-item', tag: 'li.task-list-item',
getAttrs: el => { getAttrs: el => {
const checkbox = el.querySelector('input[type=checkbox].task-list-item-checkbox'); const checkbox = el.querySelector('input[type=checkbox].task-list-item-checkbox');
......
/* eslint-disable class-methods-use-this */ import Playable from './playable';
import { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
// Transforms generated HTML back to GFM for Banzai::Filter::VideoLinkFilter // Transforms generated HTML back to GFM for Banzai::Filter::VideoLinkFilter
export default class Video extends Node { export default class Video extends Playable {
get name() { constructor() {
return 'video'; super();
} this.mediaType = 'video';
this.extraElementAttrs = { width: '400' };
get schema() {
return {
attrs: {
src: {},
alt: {
default: null,
},
},
group: 'block',
draggable: true,
parseDOM: [
{
tag: '.video-container',
skip: true,
},
{
tag: '.video-container p',
priority: 51,
ignore: true,
},
{
tag: 'video[src]',
getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }),
},
],
toDOM: node => [
'video',
{
src: node.attrs.src,
width: '400',
controls: true,
'data-setup': '{}',
'data-title': node.attrs.alt,
},
],
};
}
toMarkdown(state, node) {
defaultMarkdownSerializer.nodes.image(state, node);
state.closeBlock(node);
} }
} }
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