Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-06 18:09:05 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-06 18:09:05 +0300
commitc79da5142f46e6e9187f75c329e2c81a8568c581 (patch)
treee1411c6a9b22582f91bfbca947c343d0b36cf11a /app/assets/javascripts/content_editor
parent2e31a394c5857fdb845811685ca7fc79a2fb7540 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/content_editor')
-rw-r--r--app/assets/javascripts/content_editor/extensions/sourcemap.js8
-rw-r--r--app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js21
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js2
-rw-r--r--app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js30
-rw-r--r--app/assets/javascripts/content_editor/services/serialization_helpers.js4
5 files changed, 60 insertions, 5 deletions
diff --git a/app/assets/javascripts/content_editor/extensions/sourcemap.js b/app/assets/javascripts/content_editor/extensions/sourcemap.js
index 1cc60e33e13..deb59fde323 100644
--- a/app/assets/javascripts/content_editor/extensions/sourcemap.js
+++ b/app/assets/javascripts/content_editor/extensions/sourcemap.js
@@ -16,6 +16,10 @@ import Paragraph from './paragraph';
import Strike from './strike';
import TaskList from './task_list';
import TaskItem from './task_item';
+import Table from './table';
+import TableCell from './table_cell';
+import TableHeader from './table_header';
+import TableRow from './table_row';
export default Extension.create({
addGlobalAttributes() {
@@ -39,6 +43,10 @@ export default Extension.create({
Strike.name,
TaskList.name,
TaskItem.name,
+ Table.name,
+ TableCell.name,
+ TableHeader.name,
+ TableRow.name,
],
attributes: {
sourceMarkdown: {
diff --git a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
index 92faaabac0d..dce33889c48 100644
--- a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
+++ b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
@@ -22,7 +22,7 @@
import { Mark } from 'prosemirror-model';
import { visitParents } from 'unist-util-visit-parents';
import { toString } from 'hast-util-to-string';
-import { isFunction, noop } from 'lodash';
+import { isFunction, isString, noop } from 'lodash';
/**
* Merges two ProseMirror text nodes if both text nodes
@@ -290,6 +290,7 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, source)
selector: factorySpec.selector,
skipChildren: factorySpec.skipChildren,
processText: factorySpec.processText,
+ parent: factorySpec.parent,
};
if (factorySpec.type === 'block') {
@@ -361,6 +362,14 @@ const findFactory = (hastNode, ancestors, factories) =>
: [hastNode.tagName, hastNode.type].includes(selector);
})?.[1];
+const findParent = (ancestors, parent) => {
+ if (isString(parent)) {
+ return ancestors.reverse().find((ancestor) => ancestor.tagName === parent);
+ }
+
+ return ancestors[ancestors.length - 1];
+};
+
/**
* Converts a Hast AST to a ProseMirror document based on a series
* of specifications that describe how to map all the nodes of the former
@@ -461,6 +470,13 @@ const findFactory = (hastNode, ancestors, factories) =>
* Use this property along skipChildren to provide custom processing of child nodes
* for a block node.
*
+ * **parent**
+ *
+ * Specifies what is the node’s parent. This is useful when the node’s parent is not
+ * its direct ancestor in Abstract Syntax Tree. For example, imagine that you want
+ * to make <tr> elements a direct children of tables and skip `<thead>` and `<tbody>`
+ * altogether.
+ *
* @param {model.Document_Schema} params.schema A ProseMirror schema that specifies the shape
* of the ProseMirror document.
* @param {Object} params.factorySpec A factory specification as described above
@@ -475,7 +491,6 @@ export const createProseMirrorDocFromMdastTree = ({ schema, factorySpecs, tree,
visitParents(tree, (hastNode, ancestors) => {
const factory = findFactory(hastNode, ancestors, proseMirrorNodeFactories);
- const parent = ancestors[ancestors.length - 1];
if (!factory) {
throw new Error(
@@ -485,6 +500,8 @@ export const createProseMirrorDocFromMdastTree = ({ schema, factorySpecs, tree,
);
}
+ const parent = findParent(ancestors, factory.parent);
+
factory.handle(state, hastNode, parent);
return factory.skipChildren === true ? 'skip' : true;
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index dccc545f6cb..d5c4da8c76c 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -193,7 +193,7 @@ const defaultSerializerConfig = {
state.write('[[_TOC_]]');
state.closeBlock(node);
},
- [Table.name]: renderTable,
+ [Table.name]: preserveUnchanged(renderTable),
[TableCell.name]: renderTableCell,
[TableHeader.name]: renderTableCell,
[TableRow.name]: renderTableRow,
diff --git a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
index bec18bcdd81..9fb0d520848 100644
--- a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
+++ b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
@@ -10,6 +10,11 @@ const isTaskItem = (hastNode) => {
);
};
+const getTableCellAttrs = (hastNode) => ({
+ colspan: parseInt(hastNode.properties.colSpan, 10) || 1,
+ rowspan: parseInt(hastNode.properties.rowSpan, 10) || 1,
+});
+
const factorySpecs = {
blockquote: { type: 'block', selector: 'blockquote' },
paragraph: { type: 'block', selector: 'p' },
@@ -81,6 +86,31 @@ const factorySpecs = {
selector: (hastNode, ancestors) =>
hastNode.tagName === 'input' && isTaskItem(ancestors[ancestors.length - 1]),
},
+ table: {
+ type: 'block',
+ selector: 'table',
+ },
+ tableRow: {
+ type: 'block',
+ selector: 'tr',
+ parent: 'table',
+ },
+ tableHeader: {
+ type: 'block',
+ selector: 'th',
+ getAttrs: getTableCellAttrs,
+ wrapTextInParagraph: true,
+ },
+ tableCell: {
+ type: 'block',
+ selector: 'td',
+ getAttrs: getTableCellAttrs,
+ wrapTextInParagraph: true,
+ },
+ ignoredTableNodes: {
+ type: 'ignore',
+ selector: (hastNode) => ['thead', 'tbody', 'tfoot'].includes(hastNode.tagName),
+ },
image: {
type: 'inline',
selector: 'img',
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index 4019b772269..055a32420b2 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -1,4 +1,4 @@
-import { uniq, isString } from 'lodash';
+import { uniq, isString, omit } from 'lodash';
const defaultAttrs = {
td: { colspan: 1, rowspan: 1, colwidth: null },
@@ -219,7 +219,7 @@ function renderTableRowAsHTML(state, node) {
node.forEach((cell, _, i) => {
const tag = cell.type.name === 'tableHeader' ? 'th' : 'td';
- renderTagOpen(state, tag, cell.attrs);
+ renderTagOpen(state, tag, omit(cell.attrs, 'sourceMapKey', 'sourceMarkdown'));
if (!containsParagraphWithOnlyText(cell)) {
state.closeBlock(node);