From 54550b238617a1bb81516dd84061df1924fcd452 Mon Sep 17 00:00:00 2001 From: Erick Wilder Date: Sat, 13 Oct 2018 16:45:22 +0200 Subject: [PATCH] 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. --- package.json | 5 +- .../src/commands/markInputRule.js | 13 ++-- .../src/commands/splitToDefaultListItem.js | 59 +++++++++--------- packages/tiptap-extensions/src/marks/Bold.js | 4 +- .../tiptap-extensions/src/marks/Italic.js | 2 +- .../src/plugins/Suggestions.js | 60 ++++++++++--------- .../tiptap-utils/src/utils/getMarkAttrs.js | 2 +- packages/tiptap/src/utils/buildMenuActions.js | 4 +- 8 files changed, 80 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index dd0391e40..07ce68cd2 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "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: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": { "presets": [ diff --git a/packages/tiptap-commands/src/commands/markInputRule.js b/packages/tiptap-commands/src/commands/markInputRule.js index 02f212727..379e987de 100644 --- a/packages/tiptap-commands/src/commands/markInputRule.js +++ b/packages/tiptap-commands/src/commands/markInputRule.js @@ -2,23 +2,24 @@ import { InputRule } from 'prosemirror-inputrules' export default function (regexp, markType, getAttrs) { return new InputRule(regexp, (state, match, start, end) => { - let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs - let tr = state.tr + const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs + const { tr } = state + let markEnd = end if (match[1]) { const startSpaces = match[0].search(/\S/) - let textStart = start + match[0].indexOf(match[1]) - let textEnd = textStart + match[1].length + const textStart = start + match[0].indexOf(match[1]) + const textEnd = textStart + match[1].length if (textEnd < end) { tr.delete(textEnd, end) } if (textStart > start) { 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. return tr }) diff --git a/packages/tiptap-commands/src/commands/splitToDefaultListItem.js b/packages/tiptap-commands/src/commands/splitToDefaultListItem.js index ba4fd60e7..9d209eab9 100644 --- a/packages/tiptap-commands/src/commands/splitToDefaultListItem.js +++ b/packages/tiptap-commands/src/commands/splitToDefaultListItem.js @@ -1,73 +1,76 @@ // this is a copy of canSplit // 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) { - let $pos = doc.resolve(pos), base = $pos.depth - depth - let innerType = (typesAfter && typesAfter[typesAfter.length - 1]) || $pos.parent - if (base < 0 || $pos.parent.type.spec.isolating || - !$pos.parent.canReplace($pos.index(), $pos.parent.childCount) || - !innerType.type.validContent($pos.parent.content.cutByIndex($pos.index(), $pos.parent.childCount))) - return false + const $pos = doc.resolve(pos); const +base = $pos.depth - depth + const innerType = (typesAfter && typesAfter[typesAfter.length - 1]) || $pos.parent + if (base < 0 || $pos.parent.type.spec.isolating + || !$pos.parent.canReplace($pos.index(), $pos.parent.childCount) + || !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--) { - 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 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)) /* Change starts from here */ // if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest)) // return false - if (!node.canReplace(index + 1, node.childCount)) - return false + if (!node.canReplace(index + 1, node.childCount)) return false /* Change ends here */ } - let index = $pos.indexAfter(base) - let baseType = typesAfter && typesAfter[0] + const index = $pos.indexAfter(base) + const baseType = typesAfter && typesAfter[0] return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type) } // this is a copy of splitListItem // see https://github.com/ProseMirror/prosemirror-schema-list/blob/master/src/schema-list.js -export default function (itemType) { - return function(state, dispatch) { - let {$from, $to, node} = state.selection +export default function splitListItem(itemType) { + return function _splitListItem(state, dispatch) { + const { $from, $to, node } = state.selection 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 ($from.parent.content.size == 0) { // In an empty block. If this is a nested list, the wrapping // list item should be split. Otherwise, bail out and let next // command handle lifting. - if ($from.depth == 2 || $from.node(-3).type != itemType || - $from.index(-2) != $from.node(-2).childCount - 1) return false + if ($from.depth == 2 || $from.node(-3).type != itemType + || $from.index(-2) != $from.node(-2).childCount - 1) return false 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 // 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--) - wrap = Fragment.from($from.node(d).copy(wrap)) + for (let d = $from.depth - (keepItem ? 1 : 2); d >= $from.depth - 3; d--) wrap = Fragment.from($from.node(d).copy(wrap)) // Add a second list item with an empty default start node 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)))) dispatch(tr.scrollIntoView()) } return true } - let nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null - let tr = state.tr.delete($from.pos, $to.pos) + const nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null + const tr = state.tr.delete($from.pos, $to.pos) /* Change starts from here */ // let types = nextType && [null, {type: nextType}] - let types = nextType && [{type: itemType}, {type: nextType}] - if (!types) types = [{type: itemType}, null] + let types = nextType && [{ type: itemType }, { type: nextType }] + if (!types) types = [{ type: itemType }, null] /* Change ends here */ if (!canSplit(tr.doc, $from.pos, 2, types)) return false - if (dispatch) dispatch(tr.split($from.pos, 2, [{type: state.schema.nodes.todo_item, attrs: { done: false }}]).scrollIntoView()) + if (dispatch) dispatch(tr.split($from.pos, 2, [{ type: state.schema.nodes.todo_item, attrs: { done: false } }]).scrollIntoView()) return true } -} \ No newline at end of file +} +/* eslint-enable max-len, no-plusplus, no-undef, eqeqeq */ diff --git a/packages/tiptap-extensions/src/marks/Bold.js b/packages/tiptap-extensions/src/marks/Bold.js index a6dba903b..c6ca2db7c 100644 --- a/packages/tiptap-extensions/src/marks/Bold.js +++ b/packages/tiptap-extensions/src/marks/Bold.js @@ -15,7 +15,7 @@ export default class BoldMark extends Mark { }, { tag: 'b', - getAttrs: node => node.style.fontWeight != 'normal' && null, + getAttrs: node => node.style.fontWeight !== 'normal' && null, }, { style: 'font-weight', @@ -38,7 +38,7 @@ export default class BoldMark extends Mark { inputRules({ type }) { return [ - markInputRule(/(?:\*\*|__)([^\*_]+)(?:\*\*|__)$/, type), + markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type), ] } diff --git a/packages/tiptap-extensions/src/marks/Italic.js b/packages/tiptap-extensions/src/marks/Italic.js index 6a513f375..a0066fb20 100644 --- a/packages/tiptap-extensions/src/marks/Italic.js +++ b/packages/tiptap-extensions/src/marks/Italic.js @@ -30,7 +30,7 @@ export default class ItalicMark extends Mark { inputRules({ type }) { return [ - markInputRule(/(?:^|[^\*_])(?:\*|_)([^\*_]+)(?:\*|_)$/, type), + markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, type), ] } diff --git a/packages/tiptap-extensions/src/plugins/Suggestions.js b/packages/tiptap-extensions/src/plugins/Suggestions.js index 9d3a2d08e..cb697b7c5 100644 --- a/packages/tiptap-extensions/src/plugins/Suggestions.js +++ b/packages/tiptap-extensions/src/plugins/Suggestions.js @@ -22,37 +22,39 @@ function triggerCharacter({ const textTo = $position.end() const text = $position.doc.textBetween(textFrom, textTo, '\0', '\0') - let match + let match = regexp.exec(text) + let position + while (match !== null) { + // JavaScript doesn't have lookbehinds; this hacks a check that first character is " " + // or the line beginning + const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index) + if (/^[\s\0]?$/.test(matchPrefix)) { + // The absolute position of the match in the document + const from = match.index + $position.start() + let to = from + match[0].length - while ((match = regexp.exec(text))) { - // Javascript doesn't have lookbehinds; this hacks a check that first character is " " or the line beginning - const prefix = match.input.slice(Math.max(0, match.index - 1), match.index) - if (!/^[\s\0]?$/.test(prefix)) { - continue + // 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))) { + match[0] += ' ' + to += 1 + } + + // If the $position is located within the matched substring, return that range + if (from < $position.pos && to >= $position.pos) { + position = { + range: { + from, + to, + }, + query: match[0].slice(char.length), + text: match[0], + } + } } - - // The absolute position of the match in the document - const from = match.index + $position.start() - let to = from + match[0].length - - // 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))) { - match[0] += ' ' - to++ - } - - // If the $position is located within the matched substring, return that range - if (from < $position.pos && to >= $position.pos) { - return { - range: { - from, - to, - }, - query: match[0].slice(char.length), - text: match[0], - } - } - } + match = regexp.exec(text) + } + return position } } diff --git a/packages/tiptap-utils/src/utils/getMarkAttrs.js b/packages/tiptap-utils/src/utils/getMarkAttrs.js index 94e8fb160..27ee1244a 100644 --- a/packages/tiptap-utils/src/utils/getMarkAttrs.js +++ b/packages/tiptap-utils/src/utils/getMarkAttrs.js @@ -6,7 +6,7 @@ export default function (state, type) { 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) { return mark.attrs diff --git a/packages/tiptap/src/utils/buildMenuActions.js b/packages/tiptap/src/utils/buildMenuActions.js index c179060b6..95ec82982 100644 --- a/packages/tiptap/src/utils/buildMenuActions.js +++ b/packages/tiptap/src/utils/buildMenuActions.js @@ -28,7 +28,9 @@ export default function ({ schema, state, commands }) { command, } }) - .reduce((actions, { name, active, attrs, command }) => ({ + .reduce((actions, { + name, active, attrs, command, +}) => ({ ...actions, [name]: { active,