mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-28 17:02:04 +03:00
Added bg-color mark, added color grid selectors
This commit is contained in:
@ -30,6 +30,20 @@ marks.subscript = {
|
|||||||
close: '</sub>',
|
close: '</sub>',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
marks.text_color = {
|
||||||
|
open(state, mark, parent, index) {
|
||||||
|
return `<span style="color: ${mark.attrs.color};">`
|
||||||
|
},
|
||||||
|
close: '</span>',
|
||||||
|
};
|
||||||
|
|
||||||
|
marks.background_color = {
|
||||||
|
open(state, mark, parent, index) {
|
||||||
|
return `<span style="background-color: ${mark.attrs.color};">`
|
||||||
|
},
|
||||||
|
close: '</span>',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
function writeNodeAsHtml(state, node) {
|
function writeNodeAsHtml(state, node) {
|
||||||
const html = docToHtml({ content: [node] });
|
const html = docToHtml({ content: [node] });
|
||||||
@ -43,11 +57,11 @@ function writeNodeAsHtml(state, node) {
|
|||||||
// or element that cannot be represented in commonmark without losing
|
// or element that cannot be represented in commonmark without losing
|
||||||
// formatting or content.
|
// formatting or content.
|
||||||
for (const [nodeType, serializerFunction] of Object.entries(nodes)) {
|
for (const [nodeType, serializerFunction] of Object.entries(nodes)) {
|
||||||
nodes[nodeType] = function(state, node) {
|
nodes[nodeType] = function(state, node, parent, index) {
|
||||||
if (node.attrs.align) {
|
if (node.attrs.align) {
|
||||||
writeNodeAsHtml(state, node);
|
writeNodeAsHtml(state, node);
|
||||||
} else {
|
} else {
|
||||||
serializerFunction(state, node);
|
serializerFunction(state, node, parent, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
resources/js/editor/menu/ColorPickerGrid.js
Normal file
40
resources/js/editor/menu/ColorPickerGrid.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import crel from "crelt"
|
||||||
|
const prefix = "ProseMirror-menu"
|
||||||
|
import {toggleMark} from "prosemirror-commands";
|
||||||
|
|
||||||
|
class ColorPickerGrid {
|
||||||
|
|
||||||
|
constructor(markType, attrName, colors) {
|
||||||
|
this.markType = markType;
|
||||||
|
this.colors = colors
|
||||||
|
this.attrName = attrName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// :: (EditorView) → {dom: dom.Node, update: (EditorState) → bool}
|
||||||
|
// Renders the submenu.
|
||||||
|
render(view) {
|
||||||
|
|
||||||
|
const colorElems = [];
|
||||||
|
for (const color of this.colors) {
|
||||||
|
const elem = crel("div", {class: prefix + "-color-grid-item", style: `background-color: ${color};`});
|
||||||
|
colorElems.push(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrap = crel("div", {class: prefix + "-color-grid-container"}, colorElems);
|
||||||
|
wrap.addEventListener('click', event => {
|
||||||
|
if (event.target.classList.contains(prefix + "-color-grid-item")) {
|
||||||
|
const color = event.target.style.backgroundColor;
|
||||||
|
const attrs = {[this.attrName]: color};
|
||||||
|
toggleMark(this.markType, attrs)(view.state, view.dispatch, view, event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function update(state) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {dom: wrap, update}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ColorPickerGrid;
|
@ -2,6 +2,7 @@ import {
|
|||||||
MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
|
MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
|
||||||
undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem,
|
undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem,
|
||||||
} from "./menu"
|
} from "./menu"
|
||||||
|
import ColorPickerGrid from "./ColorPickerGrid";
|
||||||
|
|
||||||
import {toggleMark} from "prosemirror-commands";
|
import {toggleMark} from "prosemirror-commands";
|
||||||
import {menuBar} from "./menubar"
|
import {menuBar} from "./menubar"
|
||||||
@ -117,9 +118,15 @@ const alignments = [
|
|||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const colorOptions = ["#000000","#993300","#333300","#003300","#003366","#000080","#333399","#333333","#800000","#FF6600","#808000","#008000","#008080","#0000FF","#666699","#808080","#FF0000","#FF9900","#99CC00","#339966","#33CCCC","#3366FF","#800080","#999999","#FF00FF","#FFCC00","#FFFF00","#00FF00","#00FFFF","#00CCFF","#993366","#FFFFFF","#FF99CC","#FFCC99","#FFFF99","#CCFFCC","#CCFFFF","#99CCFF","#CC99FF"];
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
markItem(schema.marks.text_color, {title: "Green", label: "Green", attrs: {color: '#00FF00'}}),
|
new DropdownSubmenu([
|
||||||
markItem(schema.marks.text_color, {title: "Blue", label: "Blue", attrs: {color: '#0000FF'}}),
|
new ColorPickerGrid(schema.marks.text_color, 'color', colorOptions),
|
||||||
|
], {label: 'Text Color'}),
|
||||||
|
new DropdownSubmenu([
|
||||||
|
new ColorPickerGrid(schema.marks.background_color, 'color', colorOptions),
|
||||||
|
], {label: 'Background Color'}),
|
||||||
];
|
];
|
||||||
|
|
||||||
const menu = menuBar({
|
const menu = menuBar({
|
||||||
@ -127,8 +134,8 @@ const menu = menuBar({
|
|||||||
content: [
|
content: [
|
||||||
[undoItem, redoItem],
|
[undoItem, redoItem],
|
||||||
[new DropdownSubmenu(formats, { label: 'Formats' })],
|
[new DropdownSubmenu(formats, { label: 'Formats' })],
|
||||||
colors,
|
|
||||||
inlineStyles,
|
inlineStyles,
|
||||||
|
colors,
|
||||||
alignments,
|
alignments,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import crel from "crelt"
|
import crel from "crelt"
|
||||||
import {lift, joinUp, selectParentNode, wrapIn, setBlockType} from "prosemirror-commands"
|
import {lift, joinUp, selectParentNode, wrapIn, setBlockType, toggleMark} from "prosemirror-commands"
|
||||||
import {undo, redo} from "prosemirror-history"
|
import {undo, redo} from "prosemirror-history"
|
||||||
import {setBlockAttr} from "../commands";
|
import {setBlockAttr} from "../commands";
|
||||||
|
|
||||||
@ -321,6 +321,8 @@ function separator() {
|
|||||||
return crel("span", {class: prefix + "separator"})
|
return crel("span", {class: prefix + "separator"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// :: Object
|
// :: Object
|
||||||
// A set of basic editor-related icons. Contains the properties
|
// A set of basic editor-related icons. Contains the properties
|
||||||
// `join`, `lift`, `selectParentNode`, `undo`, `redo`, `strong`, `em`,
|
// `join`, `lift`, `selectParentNode`, `undo`, `redo`, `strong`, `em`,
|
||||||
|
@ -45,12 +45,28 @@ const text_color = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const background_color = {
|
||||||
|
attrs: {
|
||||||
|
color: {},
|
||||||
|
},
|
||||||
|
parseDOM: [{
|
||||||
|
style: 'background-color',
|
||||||
|
getAttrs(color) {
|
||||||
|
return {color}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
toDOM(node) {
|
||||||
|
return ['span', {style: `background-color: ${node.attrs.color};`}, 0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const marks = baseMarks.append({
|
const marks = baseMarks.append({
|
||||||
underline,
|
underline,
|
||||||
strike,
|
strike,
|
||||||
superscript,
|
superscript,
|
||||||
subscript,
|
subscript,
|
||||||
text_color,
|
text_color,
|
||||||
|
background_color,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default marks;
|
export default marks;
|
@ -366,3 +366,15 @@ img.ProseMirror-separator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ProseMirror p { margin-bottom: 1em }
|
.ProseMirror p { margin-bottom: 1em }
|
||||||
|
|
||||||
|
.ProseMirror-menu-color-grid-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(8, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-color-grid-item {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 2px solid #FFF;
|
||||||
|
display: block;
|
||||||
|
}
|
Reference in New Issue
Block a user