feat(package.json): Add lint yarn script + make it a precondition to build all packages.
fmt(tiptap-commands): Fix all ESLint violations with `--fix` fmt(tiptap-commands): Ignore some ESLint rules on code copied from prosemirror. fmt(tiptap): Apply ESLint autofix to `tiptap` package sources. fmt(tiptap-extensions): Fix ESlint violations from `marks` refactor(tiptap-extensions): Fix ESLint violations for `plugins/Suggestions.js`. Some of the violations required a bit of restructuring of the code/logic fmt(tiptap-utils): Fix ESLint violations. feat(package.json): Add yarn script to lint source code before compiling the examples.
This commit is contained in:
@@ -8,7 +8,10 @@
|
|||||||
"start": "node ./node_modules/@babel/node/bin/babel-node.js ./build/examples/server.js --env=development",
|
"start": "node ./node_modules/@babel/node/bin/babel-node.js ./build/examples/server.js --env=development",
|
||||||
"build:packages": "node ./node_modules/@babel/node/bin/babel-node.js ./build/packages/build.js",
|
"build:packages": "node ./node_modules/@babel/node/bin/babel-node.js ./build/packages/build.js",
|
||||||
"build:examples": "node ./node_modules/@babel/node/bin/babel-node.js ./build/examples/build.js --env=production",
|
"build:examples": "node ./node_modules/@babel/node/bin/babel-node.js ./build/examples/build.js --env=production",
|
||||||
"release": "yarn build:packages && lerna publish"
|
"release": "yarn build:packages && lerna publish",
|
||||||
|
"lint": "eslint ./packages/**/src/**",
|
||||||
|
"prebuild:packages": "yarn lint",
|
||||||
|
"prebuild:examples": "yarn lint"
|
||||||
},
|
},
|
||||||
"babel": {
|
"babel": {
|
||||||
"presets": [
|
"presets": [
|
||||||
|
|||||||
@@ -2,23 +2,24 @@ import { InputRule } from 'prosemirror-inputrules'
|
|||||||
|
|
||||||
export default function (regexp, markType, getAttrs) {
|
export default function (regexp, markType, getAttrs) {
|
||||||
return new InputRule(regexp, (state, match, start, end) => {
|
return new InputRule(regexp, (state, match, start, end) => {
|
||||||
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
|
const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
|
||||||
let tr = state.tr
|
const { tr } = state
|
||||||
|
let markEnd = end
|
||||||
|
|
||||||
if (match[1]) {
|
if (match[1]) {
|
||||||
const startSpaces = match[0].search(/\S/)
|
const startSpaces = match[0].search(/\S/)
|
||||||
let textStart = start + match[0].indexOf(match[1])
|
const textStart = start + match[0].indexOf(match[1])
|
||||||
let textEnd = textStart + match[1].length
|
const textEnd = textStart + match[1].length
|
||||||
if (textEnd < end) {
|
if (textEnd < end) {
|
||||||
tr.delete(textEnd, end)
|
tr.delete(textEnd, end)
|
||||||
}
|
}
|
||||||
if (textStart > start) {
|
if (textStart > start) {
|
||||||
tr.delete(start + startSpaces, textStart)
|
tr.delete(start + startSpaces, textStart)
|
||||||
}
|
}
|
||||||
end = start + startSpaces + match[1].length
|
markEnd = start + startSpaces + match[1].length
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.addMark(start, end, markType.create(attrs))
|
tr.addMark(start, markEnd, markType.create(attrs))
|
||||||
tr.removeStoredMark(markType) // Do not continue with mark.
|
tr.removeStoredMark(markType) // Do not continue with mark.
|
||||||
return tr
|
return tr
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,64 +1,66 @@
|
|||||||
// this is a copy of canSplit
|
// this is a copy of canSplit
|
||||||
// see https://github.com/ProseMirror/prosemirror-transform/blob/master/src/structure.js
|
// see https://github.com/ProseMirror/prosemirror-transform/blob/master/src/structure.js
|
||||||
|
|
||||||
|
// Since this piece of code was "borrowed" from prosemirror, ESLint rules are ignored.
|
||||||
|
/* eslint-disable max-len, no-plusplus, no-undef, eqeqeq */
|
||||||
function canSplit(doc, pos, depth = 1, typesAfter) {
|
function canSplit(doc, pos, depth = 1, typesAfter) {
|
||||||
let $pos = doc.resolve(pos), base = $pos.depth - depth
|
const $pos = doc.resolve(pos); const
|
||||||
let innerType = (typesAfter && typesAfter[typesAfter.length - 1]) || $pos.parent
|
base = $pos.depth - depth
|
||||||
if (base < 0 || $pos.parent.type.spec.isolating ||
|
const innerType = (typesAfter && typesAfter[typesAfter.length - 1]) || $pos.parent
|
||||||
!$pos.parent.canReplace($pos.index(), $pos.parent.childCount) ||
|
if (base < 0 || $pos.parent.type.spec.isolating
|
||||||
!innerType.type.validContent($pos.parent.content.cutByIndex($pos.index(), $pos.parent.childCount)))
|
|| !$pos.parent.canReplace($pos.index(), $pos.parent.childCount)
|
||||||
return false
|
|| !innerType.type.validContent($pos.parent.content.cutByIndex($pos.index(), $pos.parent.childCount))) return false
|
||||||
for (let d = $pos.depth - 1, i = depth - 2; d > base; d--, i--) {
|
for (let d = $pos.depth - 1, i = depth - 2; d > base; d--, i--) {
|
||||||
let node = $pos.node(d), index = $pos.index(d)
|
const node = $pos.node(d); const
|
||||||
|
index = $pos.index(d)
|
||||||
if (node.type.spec.isolating) return false
|
if (node.type.spec.isolating) return false
|
||||||
let rest = node.content.cutByIndex(index, node.childCount)
|
let rest = node.content.cutByIndex(index, node.childCount)
|
||||||
let after = (typesAfter && typesAfter[i]) || node
|
const after = (typesAfter && typesAfter[i]) || node
|
||||||
if (after != node) rest = rest.replaceChild(0, after.type.create(after.attrs))
|
if (after != node) rest = rest.replaceChild(0, after.type.create(after.attrs))
|
||||||
|
|
||||||
/* Change starts from here */
|
/* Change starts from here */
|
||||||
// if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest))
|
// if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest))
|
||||||
// return false
|
// return false
|
||||||
if (!node.canReplace(index + 1, node.childCount))
|
if (!node.canReplace(index + 1, node.childCount)) return false
|
||||||
return false
|
|
||||||
/* Change ends here */
|
/* Change ends here */
|
||||||
}
|
}
|
||||||
let index = $pos.indexAfter(base)
|
const index = $pos.indexAfter(base)
|
||||||
let baseType = typesAfter && typesAfter[0]
|
const baseType = typesAfter && typesAfter[0]
|
||||||
return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type)
|
return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a copy of splitListItem
|
// this is a copy of splitListItem
|
||||||
// see https://github.com/ProseMirror/prosemirror-schema-list/blob/master/src/schema-list.js
|
// see https://github.com/ProseMirror/prosemirror-schema-list/blob/master/src/schema-list.js
|
||||||
|
|
||||||
export default function (itemType) {
|
export default function splitListItem(itemType) {
|
||||||
return function(state, dispatch) {
|
return function _splitListItem(state, dispatch) {
|
||||||
let {$from, $to, node} = state.selection
|
const { $from, $to, node } = state.selection
|
||||||
if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) return false
|
if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) return false
|
||||||
let grandParent = $from.node(-1)
|
const grandParent = $from.node(-1)
|
||||||
if (grandParent.type != itemType) return false
|
if (grandParent.type != itemType) return false
|
||||||
if ($from.parent.content.size == 0) {
|
if ($from.parent.content.size == 0) {
|
||||||
// In an empty block. If this is a nested list, the wrapping
|
// In an empty block. If this is a nested list, the wrapping
|
||||||
// list item should be split. Otherwise, bail out and let next
|
// list item should be split. Otherwise, bail out and let next
|
||||||
// command handle lifting.
|
// command handle lifting.
|
||||||
if ($from.depth == 2 || $from.node(-3).type != itemType ||
|
if ($from.depth == 2 || $from.node(-3).type != itemType
|
||||||
$from.index(-2) != $from.node(-2).childCount - 1) return false
|
|| $from.index(-2) != $from.node(-2).childCount - 1) return false
|
||||||
|
|
||||||
if (dispatch) {
|
if (dispatch) {
|
||||||
let wrap = Fragment.empty, keepItem = $from.index(-1) > 0
|
let wrap = Fragment.empty; const
|
||||||
|
keepItem = $from.index(-1) > 0
|
||||||
// Build a fragment containing empty versions of the structure
|
// Build a fragment containing empty versions of the structure
|
||||||
// from the outer list item to the parent node of the cursor
|
// from the outer list item to the parent node of the cursor
|
||||||
for (let d = $from.depth - (keepItem ? 1 : 2); d >= $from.depth - 3; d--)
|
for (let d = $from.depth - (keepItem ? 1 : 2); d >= $from.depth - 3; d--) wrap = Fragment.from($from.node(d).copy(wrap))
|
||||||
wrap = Fragment.from($from.node(d).copy(wrap))
|
|
||||||
// Add a second list item with an empty default start node
|
// Add a second list item with an empty default start node
|
||||||
wrap = wrap.append(Fragment.from(itemType.createAndFill()))
|
wrap = wrap.append(Fragment.from(itemType.createAndFill()))
|
||||||
let tr = state.tr.replace($from.before(keepItem ? null : -1), $from.after(-3), new Slice(wrap, keepItem ? 3 : 2, 2))
|
const tr = state.tr.replace($from.before(keepItem ? null : -1), $from.after(-3), new Slice(wrap, keepItem ? 3 : 2, 2))
|
||||||
tr.setSelection(state.selection.constructor.near(tr.doc.resolve($from.pos + (keepItem ? 3 : 2))))
|
tr.setSelection(state.selection.constructor.near(tr.doc.resolve($from.pos + (keepItem ? 3 : 2))))
|
||||||
dispatch(tr.scrollIntoView())
|
dispatch(tr.scrollIntoView())
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
let nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null
|
const nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null
|
||||||
let tr = state.tr.delete($from.pos, $to.pos)
|
const tr = state.tr.delete($from.pos, $to.pos)
|
||||||
|
|
||||||
/* Change starts from here */
|
/* Change starts from here */
|
||||||
// let types = nextType && [null, {type: nextType}]
|
// let types = nextType && [null, {type: nextType}]
|
||||||
@@ -71,3 +73,4 @@ export default function (itemType) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* eslint-enable max-len, no-plusplus, no-undef, eqeqeq */
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default class BoldMark extends Mark {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: 'b',
|
tag: 'b',
|
||||||
getAttrs: node => node.style.fontWeight != 'normal' && null,
|
getAttrs: node => node.style.fontWeight !== 'normal' && null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
style: 'font-weight',
|
style: 'font-weight',
|
||||||
@@ -38,7 +38,7 @@ export default class BoldMark extends Mark {
|
|||||||
|
|
||||||
inputRules({ type }) {
|
inputRules({ type }) {
|
||||||
return [
|
return [
|
||||||
markInputRule(/(?:\*\*|__)([^\*_]+)(?:\*\*|__)$/, type),
|
markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default class ItalicMark extends Mark {
|
|||||||
|
|
||||||
inputRules({ type }) {
|
inputRules({ type }) {
|
||||||
return [
|
return [
|
||||||
markInputRule(/(?:^|[^\*_])(?:\*|_)([^\*_]+)(?:\*|_)$/, type),
|
markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, type),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,28 +22,27 @@ function triggerCharacter({
|
|||||||
const textTo = $position.end()
|
const textTo = $position.end()
|
||||||
const text = $position.doc.textBetween(textFrom, textTo, '\0', '\0')
|
const text = $position.doc.textBetween(textFrom, textTo, '\0', '\0')
|
||||||
|
|
||||||
let match
|
let match = regexp.exec(text)
|
||||||
|
let position
|
||||||
while ((match = regexp.exec(text))) {
|
while (match !== null) {
|
||||||
// Javascript doesn't have lookbehinds; this hacks a check that first character is " " or the line beginning
|
// JavaScript doesn't have lookbehinds; this hacks a check that first character is " "
|
||||||
const prefix = match.input.slice(Math.max(0, match.index - 1), match.index)
|
// or the line beginning
|
||||||
if (!/^[\s\0]?$/.test(prefix)) {
|
const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)
|
||||||
continue
|
if (/^[\s\0]?$/.test(matchPrefix)) {
|
||||||
}
|
|
||||||
|
|
||||||
// The absolute position of the match in the document
|
// The absolute position of the match in the document
|
||||||
const from = match.index + $position.start()
|
const from = match.index + $position.start()
|
||||||
let to = from + match[0].length
|
let to = from + match[0].length
|
||||||
|
|
||||||
// Edge case handling; if spaces are allowed and we're directly in between two triggers
|
// Edge case handling; if spaces are allowed and we're directly in between
|
||||||
|
// two triggers
|
||||||
if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {
|
if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {
|
||||||
match[0] += ' '
|
match[0] += ' '
|
||||||
to++
|
to += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the $position is located within the matched substring, return that range
|
// If the $position is located within the matched substring, return that range
|
||||||
if (from < $position.pos && to >= $position.pos) {
|
if (from < $position.pos && to >= $position.pos) {
|
||||||
return {
|
position = {
|
||||||
range: {
|
range: {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
@@ -53,6 +52,9 @@ function triggerCharacter({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match = regexp.exec(text)
|
||||||
|
}
|
||||||
|
return position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default function (state, type) {
|
|||||||
marks = [...marks, ...node.marks]
|
marks = [...marks, ...node.marks]
|
||||||
})
|
})
|
||||||
|
|
||||||
const mark = marks.find(mark => mark.type.name === type.name)
|
const mark = marks.find(markItem => markItem.type.name === type.name)
|
||||||
|
|
||||||
if (mark) {
|
if (mark) {
|
||||||
return mark.attrs
|
return mark.attrs
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ export default function ({ schema, state, commands }) {
|
|||||||
command,
|
command,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.reduce((actions, { name, active, attrs, command }) => ({
|
.reduce((actions, {
|
||||||
|
name, active, attrs, command,
|
||||||
|
}) => ({
|
||||||
...actions,
|
...actions,
|
||||||
[name]: {
|
[name]: {
|
||||||
active,
|
active,
|
||||||
|
|||||||
Reference in New Issue
Block a user