@mirus/tiptap-editor 2.1.6 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirus/tiptap-editor",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "custom setup for the tiptap editor",
5
5
  "repository": "https://github.com/mirusresearch/tiptap-editor",
6
6
  "bugs": {
package/src/App.vue CHANGED
@@ -27,7 +27,7 @@ export default {
27
27
  value: 'red',
28
28
  message: 'did you mean...',
29
29
  options: ['read', 'reed'], // optional
30
- offset: 54, // identifies which instance of the word is problematic
30
+ offset: 55, // identifies which instance of the word is problematic
31
31
  length: 3, // length of the word
32
32
  },
33
33
  {
@@ -40,7 +40,7 @@ export default {
40
40
  isWord: false,
41
41
  message: 'you sure you wanted a tag?',
42
42
  overrideClass: 'underline-blue', // optional
43
- offset: 9,
43
+ offset: 11,
44
44
  length: 8,
45
45
  },
46
46
  {
@@ -163,6 +163,7 @@ export default {
163
163
  optionsRange: null,
164
164
  initialCharacterCount: 0,
165
165
  previousCharacterCount: 0,
166
+ previousHTML: '',
166
167
  };
167
168
  },
168
169
  computed: {
@@ -290,15 +291,22 @@ export default {
290
291
  this.warnings.forEach((warning) => {
291
292
  if (warning.length && warning.offset) {
292
293
  if (editor.state.selection.head - 1 <= warning.offset) {
293
- const charCountDif =
294
+ let charCountDiff =
294
295
  this.currentCharacterCount - this.previousCharacterCount;
295
- warning.offset += charCountDif;
296
+ charCountDiff += this.adjustForNewlines();
297
+ warning.offset += charCountDiff;
296
298
  }
297
299
  }
298
300
  });
299
301
  this.previousCharacterCount = this.currentCharacterCount;
302
+ this.previousHTML = this.editor.getHTML();
300
303
  this.editor.commands.focus();
301
304
  });
305
+ this.warnings.forEach((warning) => {
306
+ if (warning.length && warning.offset >= 0) {
307
+ warning.offset += this.getOffsetAdjustment(warning);
308
+ }
309
+ });
302
310
  },
303
311
  destroyed() {
304
312
  this.editor.destroy();
@@ -307,6 +315,42 @@ export default {
307
315
  }
308
316
  },
309
317
  methods: {
318
+ // compliance checks base offset data off the HTML value of the text
319
+ // ProseMirror uses a unique token sequence indexing system - see https://prosemirror.net/docs/guide/#doc.indexing
320
+ // we need to convert warning offsets to the index values ProseMirror expects
321
+ getOffsetAdjustment(warning) {
322
+ // compliance check offsets count all HTML entities as one character, whereas the editor value does not. compensate for
323
+ // this by adding to the offset until it matches (or equals the length of the editor text as a failsafe break from the loop)
324
+ while (
325
+ this.value.substr(warning.offset, warning.value.length) !== warning.value &&
326
+ warning.offset <= this.value.length
327
+ ) {
328
+ warning.offset++;
329
+ }
330
+
331
+ // obtain the substring up until the beginning of the warning
332
+ const originalLength = warning.offset;
333
+ let substr = this.value.substr(0, warning.offset);
334
+
335
+ // these tags count as one token, so we replace them with a single space
336
+ substr = substr.replace(/<p>|<\/p>|<li>|<ul>|<\/ul>|<\/li>|<div>|<\/div>/g, ' ');
337
+
338
+ // these tags don't count as a token, so we remove them
339
+ const knownTagRegex = /<strong>|<\/strong>|<em>|<\/em>/g;
340
+ substr = substr.replace(knownTagRegex, '');
341
+
342
+ // return the number of chars the offset should be adjusted by
343
+ return substr.length - originalLength;
344
+ },
345
+ // when the user adds a newline to the text of the editor, the character count stays the same, but ProseMirror's token
346
+ // sequence indexing system adds 2 tokens to the content. We need to adjust warning offsets to account for that
347
+ adjustForNewlines() {
348
+ const regex = /<\/p><p>/g;
349
+ const previousNewlines = (this.previousHTML.match(regex) || []).length;
350
+ const newlines = (this.editor.getHTML().match(regex) || []).length;
351
+ // multiply the difference in newlines by 2 since each instance counts as 2 tokens
352
+ return (newlines - previousNewlines) * 2;
353
+ },
310
354
  getErrorWords() {
311
355
  if (this.errors.length < 1) {
312
356
  return [];
@@ -380,6 +424,12 @@ export default {
380
424
  watch: {
381
425
  warnings: function (n, o) {
382
426
  if (this.editor) {
427
+ this.warnings.forEach((warning) => {
428
+ if (warning.length && warning.offset >= 0) {
429
+ warning.offset += this.getOffsetAdjustment(warning);
430
+ }
431
+ });
432
+
383
433
  // preserve selection after updating warnings
384
434
  const oldSelection = this.editor.view.state.selection;
385
435
  // this.editor.commands.setContent(this.currentValue);
package/src/warnings.js CHANGED
@@ -70,7 +70,7 @@ function lint(doc, position, prev, getErrorWords) {
70
70
  matchingErrorWords.forEach((word) => {
71
71
  if (word.length && word.offset >= 0) {
72
72
  errorHasOffsetData = true;
73
- if (indexOfMatchedWord - 1 === word.offset) {
73
+ if (indexOfMatchedWord === word.offset) {
74
74
  record(indexOfMatchedWord, indexOfMatchedWord + m[0].length, m[0]);
75
75
  }
76
76
  }