Skip to content

Commit

Permalink
fix image domparser when rewrite is in use
Browse files Browse the repository at this point in the history
This also uses the browser's URL parser instead of parsing it ourselves.
  • Loading branch information
splitbrain committed Nov 21, 2024
1 parent e35b45a commit b7a7aa7
Showing 1 changed file with 67 additions and 58 deletions.
125 changes: 67 additions & 58 deletions script/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
* extends the basic schemas provided by ProseMirror
*/

import { schema as schemaBasic } from 'prosemirror-schema-basic';
import { tableNodes } from 'prosemirror-tables';
import { bulletList, listItem, orderedList } from 'prosemirror-schema-list';
import {schema as schemaBasic} from 'prosemirror-schema-basic';
import {tableNodes} from 'prosemirror-tables';
import {bulletList, listItem, orderedList} from 'prosemirror-schema-list';

export default function getSpec() {
let { nodes, marks } = schemaBasic.spec;
let {nodes, marks} = schemaBasic.spec;

const doc = nodes.get('doc');
doc.content = '(block | baseonly | container | protected_block | substitution_block)+';
doc.attrs = {
nocache: { default: false },
notoc: { default: false },
nocache: {default: false},
notoc: {default: false},
};
nodes = nodes.update('doc', doc);

Expand Down Expand Up @@ -58,7 +58,7 @@ export default function getSpec() {

const tableNode = nodes.get('table');
tableNode.toDOM = function toDOM() {
return ['div', { class: 'table' }, ['table', { class: 'inline' }, ['tbody', 0]]];
return ['div', {class: 'table'}, ['table', {class: 'inline'}, ['tbody', 0]]];
};
nodes.update('table', tableNode);

Expand All @@ -69,15 +69,15 @@ export default function getSpec() {
group: 'protected_block',
code: true,
toDOM() {
return ['pre', { class: 'code' }, 0];
return ['pre', {class: 'code'}, 0];
},
});

const codeBlock = nodes.get('code_block');
codeBlock.attrs = {
class: { default: 'code' },
'data-filename': { default: '' },
'data-language': { default: '' },
class: {default: 'code'},
'data-filename': {default: ''},
'data-language': {default: ''},
};
codeBlock.toDOM = function toDOM(node) {
return ['pre', node.attrs, 0];
Expand All @@ -88,16 +88,16 @@ export default function getSpec() {
const quote = nodes.get('blockquote');
quote.content = '(block | blockquote | protected_block)+';
quote.group = 'container';
quote.toDom = () => ['blockquote', {}, ['div', { class: 'no' }, 0]];
quote.toDom = () => ['blockquote', {}, ['div', {class: 'no'}, 0]];
nodes.update('blockquote', quote);

const imageNode = nodes.get('image');
imageNode.attrs.width = { default: '' };
imageNode.attrs.height = { default: '' };
imageNode.attrs.align = { default: '' };
imageNode.attrs.linking = { default: '' };
imageNode.attrs.cache = { default: '' };
imageNode.attrs['data-resolvedHtml'] = { default: '' };
imageNode.attrs.width = {default: ''};
imageNode.attrs.height = {default: ''};
imageNode.attrs.align = {default: ''};
imageNode.attrs.linking = {default: ''};
imageNode.attrs.cache = {default: ''};
imageNode.attrs['data-resolvedHtml'] = {default: ''};
imageNode.attrs.id = {};
delete imageNode.attrs.src;
imageNode.parseDOM = [
Expand All @@ -106,16 +106,24 @@ export default function getSpec() {
getAttrs: function getAttrs(dom) {
const src = dom.getAttribute('src');
const dokuWikiFetch = `${DOKU_BASE}lib/exe/fetch.php`;
if (!src.includes(dokuWikiFetch)) {
const dokuWikiMedia = `${DOKU_BASE}_media/`;

let id = '';
let url;
try {
url = new URL(src, window.location.href);
} catch (e) {
return undefined; // let another rule handle this case
}
const [, query] = src.split('?');
const attrs = query.split('&')
.map(item => item.split('='))
.reduce((acc, [key, value]) => {
acc[key] = decodeURIComponent(value);
return acc;
}, {});

if (src.includes(dokuWikiFetch)) {
id = url.searchParams.get('media');
} else if (src.includes(dokuWikiMedia)) {
id = url.pathname.split('/').pop();
id = id.replaceAll(';', ':'); // on windows, semicolons might be used as namespace separator
}
if (!id) return undefined; // let another rule handle this case

let align = '';
if (dom.classList.contains('medialeft')) {
align = 'left';
Expand All @@ -124,12 +132,13 @@ export default function getSpec() {
} else if (dom.classList.contains('mediacenter')) {
align = 'center';
}

return {
// a relative ID might be preferred (see imgpaste plugin)
id: dom.dataset.relID || attrs.media,
id: dom.dataset.relid || id,
title: dom.getAttribute('alt'),
width: attrs.w,
height: attrs.h,
width: url.searchParams.get('w'),
height: url.searchParams.get('h'),
align,
'data-resolvedHtml': dom.outerHTML,
};
Expand All @@ -153,7 +162,7 @@ export default function getSpec() {

const imageAttrs = {};
Object.keys(imageNode.attrs).forEach((key) => {
imageAttrs[`image-${key}`] = { default: null };
imageAttrs[`image-${key}`] = {default: null};
});

nodes = nodes.addToEnd('link', {
Expand All @@ -162,13 +171,13 @@ export default function getSpec() {
attrs: {
'data-type': {},
'data-inner': {},
'data-name': { default: null },
'data-resolvedID': { default: null },
'data-resolvedUrl': { default: null },
'data-resolvedName': { default: null },
'data-resolvedClass': { default: null },
'data-resolvedTitle': { default: null },
'data-resolvedImage': { default: '' },
'data-name': {default: null},
'data-resolvedID': {default: null},
'data-resolvedUrl': {default: null},
'data-resolvedName': {default: null},
'data-resolvedClass': {default: null},
'data-resolvedTitle': {default: null},
'data-resolvedImage': {default: ''},
...imageAttrs,
},
toDOM(node) {
Expand All @@ -180,7 +189,7 @@ export default function getSpec() {
content: '',
marks: '',
attrs: {
contentJSON: { default: '' },
contentJSON: {default: ''},
},
group: 'inline',
inline: true,
Expand Down Expand Up @@ -209,7 +218,7 @@ export default function getSpec() {
return false;
}
const syntax = dom.getAttribute('alt');
return { icon, syntax };
return {icon, syntax};
},
}],
});
Expand All @@ -218,24 +227,24 @@ export default function getSpec() {
group: 'substitution_block',
atom: true,
attrs: {
class: { default: 'rss' },
class: {default: 'rss'},
url: {},
max: { default: 8 },
reverse: { default: null },
author: { default: null },
date: { default: null },
details: { default: null },
refresh: { default: '' },
renderedHTML: { default: null },
max: {default: 8},
reverse: {default: null},
author: {default: null},
date: {default: null},
details: {default: null},
refresh: {default: ''},
renderedHTML: {default: null},
},
});

nodes = nodes.addToEnd('dwplugin_block', {
content: 'text*',
marks: '',
attrs: {
class: { default: 'dwplugin' },
'data-pluginname': { default: ' ' },
class: {default: 'dwplugin'},
'data-pluginname': {default: ' '},
},
draggable: true,
inline: false,
Expand All @@ -252,8 +261,8 @@ export default function getSpec() {
nodes = nodes.addToEnd('dwplugin_inline', {
content: 'text*',
attrs: {
class: { default: 'dwplugin' },
'data-pluginname': { default: ' ' },
class: {default: 'dwplugin'},
'data-pluginname': {default: ' '},
},
marks: '',
draggable: true,
Expand All @@ -275,7 +284,7 @@ export default function getSpec() {

marks = marks.addToEnd('deleted', {
parseDOM: [
{ tag: 'del' },
{tag: 'del'},
{
style: 'text-decoration',
// https://discuss.prosemirror.net/t/dom-parsing-and-getattrs/612
Expand All @@ -289,7 +298,7 @@ export default function getSpec() {

marks = marks.addToEnd('underline', {
parseDOM: [
{ tag: 'u' },
{tag: 'u'},
{
style: 'text-decoration',
getAttrs: value => value === 'underline' && null,
Expand All @@ -302,7 +311,7 @@ export default function getSpec() {

marks = marks.addToEnd('subscript', {
parseDOM: [
{ tag: 'sub' },
{tag: 'sub'},
{
style: 'vertical-align',
getAttrs: value => value === 'sub' && null,
Expand All @@ -315,7 +324,7 @@ export default function getSpec() {

marks = marks.addToEnd('superscript', {
parseDOM: [
{ tag: 'sup' },
{tag: 'sup'},
{
style: 'vertical-align',
getAttrs: value => value === 'super' && null,
Expand All @@ -329,15 +338,15 @@ export default function getSpec() {
marks = marks.addToEnd('unformatted', {
excludes: '_',
toDOM() {
return ['span', { class: 'unformatted' }];
return ['span', {class: 'unformatted'}];
},
});

if (window.Prosemirror && window.Prosemirror.pluginSchemas) {
window.Prosemirror.pluginSchemas.forEach((addSchema) => {
({ nodes, marks } = addSchema(nodes, marks));
({nodes, marks} = addSchema(nodes, marks));
});
}

return { nodes, marks };
return {nodes, marks};
}

0 comments on commit b7a7aa7

Please sign in to comment.