tiny-markdown-editor 0.2.0 → 0.2.1

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/lib/TinyMDE.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import { GrammarRule } from "./grammar";
1
2
  export interface EditorProps {
2
3
  element?: string | HTMLElement;
3
4
  editor?: string | HTMLElement;
4
5
  content?: string;
5
6
  textarea?: string | HTMLTextAreaElement;
7
+ customInlineGrammar?: Record<string, GrammarRule>;
6
8
  }
7
9
  export interface Position {
8
10
  row: number;
@@ -38,6 +40,8 @@ export declare class Editor {
38
40
  linkLabels: string[];
39
41
  lineDirty: boolean[];
40
42
  lastCommandState: Record<string, boolean | null> | null;
43
+ private customInlineGrammar;
44
+ private mergedInlineGrammar;
41
45
  listeners: {
42
46
  change: EventHandler<ChangeEvent>[];
43
47
  selection: EventHandler<SelectionEvent>[];
package/lib/TinyMDE.js CHANGED
@@ -14,6 +14,8 @@ class Editor {
14
14
  this.linkLabels = [];
15
15
  this.lineDirty = [];
16
16
  this.lastCommandState = null;
17
+ this.customInlineGrammar = {};
18
+ this.mergedInlineGrammar = grammar_1.inlineGrammar;
17
19
  this.listeners = {
18
20
  change: [],
19
21
  selection: [],
@@ -33,6 +35,8 @@ class Editor {
33
35
  this.linkLabels = [];
34
36
  this.lineDirty = [];
35
37
  this.lastCommandState = null;
38
+ this.customInlineGrammar = props.customInlineGrammar || {};
39
+ this.mergedInlineGrammar = (0, grammar_1.createMergedInlineGrammar)(this.customInlineGrammar);
36
40
  this.listeners = {
37
41
  change: [],
38
42
  selection: [],
@@ -555,17 +559,31 @@ class Editor {
555
559
  outer: while (string) {
556
560
  // Process simple rules (non-delimiter)
557
561
  for (let rule of ["escape", "code", "autolink", "html"]) {
558
- let cap = grammar_1.inlineGrammar[rule].regexp.exec(string);
559
- if (cap) {
560
- string = string.substr(cap[0].length);
561
- offset += cap[0].length;
562
- processed += grammar_1.inlineGrammar[rule].replacement.replace(/\$([1-9])/g, (str, p1) => (0, grammar_1.htmlescape)(cap[p1]));
563
- continue outer;
562
+ if (this.mergedInlineGrammar[rule]) {
563
+ let cap = this.mergedInlineGrammar[rule].regexp.exec(string);
564
+ if (cap) {
565
+ string = string.substr(cap[0].length);
566
+ offset += cap[0].length;
567
+ processed += this.mergedInlineGrammar[rule].replacement.replace(/\$([1-9])/g, (str, p1) => (0, grammar_1.htmlescape)(cap[p1]));
568
+ continue outer;
569
+ }
570
+ }
571
+ }
572
+ // Process custom inline grammar rules
573
+ for (let rule in this.customInlineGrammar) {
574
+ if (rule !== "escape" && rule !== "code" && rule !== "autolink" && rule !== "html" && rule !== "linkOpen" && rule !== "imageOpen" && rule !== "linkLabel" && rule !== "default") {
575
+ let cap = this.mergedInlineGrammar[rule].regexp.exec(string);
576
+ if (cap) {
577
+ string = string.substr(cap[0].length);
578
+ offset += cap[0].length;
579
+ processed += this.mergedInlineGrammar[rule].replacement.replace(/\$([1-9])/g, (str, p1) => (0, grammar_1.htmlescape)(cap[p1]));
580
+ continue outer;
581
+ }
564
582
  }
565
583
  }
566
584
  // Check for links / images
567
- let potentialLink = string.match(grammar_1.inlineGrammar.linkOpen.regexp);
568
- let potentialImage = string.match(grammar_1.inlineGrammar.imageOpen.regexp);
585
+ let potentialLink = string.match(this.mergedInlineGrammar.linkOpen.regexp);
586
+ let potentialImage = string.match(this.mergedInlineGrammar.imageOpen.regexp);
569
587
  if (potentialImage || potentialLink) {
570
588
  let result = this.parseLinkOrImage(string, !!potentialImage);
571
589
  if (result) {
@@ -673,11 +691,11 @@ class Editor {
673
691
  continue outer;
674
692
  }
675
693
  // Process 'default' rule
676
- cap = grammar_1.inlineGrammar.default.regexp.exec(string);
694
+ cap = this.mergedInlineGrammar.default.regexp.exec(string);
677
695
  if (cap) {
678
696
  string = string.substr(cap[0].length);
679
697
  offset += cap[0].length;
680
- processed += grammar_1.inlineGrammar.default.replacement.replace(/\$([1-9])/g, (str, p1) => (0, grammar_1.htmlescape)(cap[p1]));
698
+ processed += this.mergedInlineGrammar.default.replacement.replace(/\$([1-9])/g, (str, p1) => (0, grammar_1.htmlescape)(cap[p1]));
681
699
  continue outer;
682
700
  }
683
701
  throw "Infinite loop!";
@@ -924,20 +942,20 @@ class Editor {
924
942
  let string = originalString.substr(currentOffset);
925
943
  // Capture any escapes and code blocks at current position
926
944
  for (let rule of ["escape", "code", "autolink", "html"]) {
927
- let cap = grammar_1.inlineGrammar[rule].regexp.exec(string);
945
+ let cap = this.mergedInlineGrammar[rule].regexp.exec(string);
928
946
  if (cap) {
929
947
  currentOffset += cap[0].length;
930
948
  continue textOuter;
931
949
  }
932
950
  }
933
951
  // Check for image
934
- if (string.match(grammar_1.inlineGrammar.imageOpen.regexp)) {
952
+ if (string.match(this.mergedInlineGrammar.imageOpen.regexp)) {
935
953
  bracketLevel++;
936
954
  currentOffset += 2;
937
955
  continue textOuter;
938
956
  }
939
957
  // Check for link
940
- if (string.match(grammar_1.inlineGrammar.linkOpen.regexp)) {
958
+ if (string.match(this.mergedInlineGrammar.linkOpen.regexp)) {
941
959
  bracketLevel++;
942
960
  if (!isImage) {
943
961
  if (this.parseLinkOrImage(string, false)) {
@@ -967,12 +985,12 @@ class Editor {
967
985
  // REFERENCE LINKS
968
986
  if (nextChar === "[") {
969
987
  let string = originalString.substr(currentOffset);
970
- let cap = grammar_1.inlineGrammar.linkLabel.regexp.exec(string);
988
+ let cap = this.mergedInlineGrammar.linkLabel.regexp.exec(string);
971
989
  if (cap) {
972
990
  currentOffset += cap[0].length;
973
991
  linkLabel.push(cap[1], cap[2], cap[3]);
974
- if (cap[grammar_1.inlineGrammar.linkLabel.labelPlaceholder]) {
975
- linkRef = cap[grammar_1.inlineGrammar.linkLabel.labelPlaceholder];
992
+ if (cap[this.mergedInlineGrammar.linkLabel.labelPlaceholder]) {
993
+ linkRef = cap[this.mergedInlineGrammar.linkLabel.labelPlaceholder];
976
994
  }
977
995
  else {
978
996
  linkRef = linkText.trim();
@@ -1033,7 +1051,7 @@ class Editor {
1033
1051
  continue inlineOuter;
1034
1052
  }
1035
1053
  // Process backslash escapes
1036
- cap = grammar_1.inlineGrammar.escape.regexp.exec(string);
1054
+ cap = this.mergedInlineGrammar.escape.regexp.exec(string);
1037
1055
  if (cap) {
1038
1056
  switch (linkDetails.length) {
1039
1057
  case 0:
package/lib/grammar.d.ts CHANGED
@@ -49,6 +49,13 @@ export declare const htmlBlockGrammar: HTMLBlockRule[];
49
49
  * In the regular expressions, replacements from the object 'replacements' will be processed before compiling into the property regexp.
50
50
  */
51
51
  export declare const inlineGrammar: Record<string, GrammarRule>;
52
+ /**
53
+ * Creates a merged inline grammar by combining the default inline grammar with custom rules.
54
+ * Custom rules are processed and their regexp patterns are expanded with replacements.
55
+ * @param customRules - Object containing custom inline grammar rules
56
+ * @returns Merged inline grammar object
57
+ */
58
+ export declare function createMergedInlineGrammar(customRules?: Record<string, GrammarRule>): Record<string, GrammarRule>;
52
59
  /**
53
60
  * Escapes HTML special characters (<, >, and &) in the string.
54
61
  * @param {string} string The raw string to be escaped
package/lib/grammar.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.commands = exports.inlineGrammar = exports.htmlBlockGrammar = exports.lineGrammar = exports.punctuationTrailing = exports.punctuationLeading = void 0;
4
+ exports.createMergedInlineGrammar = createMergedInlineGrammar;
4
5
  exports.htmlescape = htmlescape;
5
6
  const replacements = {
6
7
  ASCIIPunctuation: /[!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~\\]/,
@@ -178,6 +179,32 @@ for (let rule of exports.htmlBlockGrammar) {
178
179
  }
179
180
  rule.start = new RegExp(re, rule.start.flags);
180
181
  }
182
+ /**
183
+ * Creates a merged inline grammar by combining the default inline grammar with custom rules.
184
+ * Custom rules are processed and their regexp patterns are expanded with replacements.
185
+ * @param customRules - Object containing custom inline grammar rules
186
+ * @returns Merged inline grammar object
187
+ */
188
+ function createMergedInlineGrammar(customRules = {}) {
189
+ const merged = { ...exports.inlineGrammar };
190
+ // Process custom rules
191
+ for (const [ruleName, rule] of Object.entries(customRules)) {
192
+ // Copy the rule to avoid modifying the original
193
+ const processedRule = { ...rule };
194
+ // Process replacements in the regexp
195
+ let regexpSource = rule.regexp.source;
196
+ const replacementRegexp = new RegExp(Object.keys(replacements).join('|'));
197
+ // Replace while there is something to replace
198
+ while (regexpSource.match(replacementRegexp)) {
199
+ regexpSource = regexpSource.replace(replacementRegexp, (match) => {
200
+ return replacements[match].source;
201
+ });
202
+ }
203
+ processedRule.regexp = new RegExp(regexpSource, rule.regexp.flags);
204
+ merged[ruleName] = processedRule;
205
+ }
206
+ return merged;
207
+ }
181
208
  /**
182
209
  * Escapes HTML special characters (<, >, and &) in the string.
183
210
  * @param {string} string The raw string to be escaped
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-markdown-editor",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "TinyMDE: A tiny, ultra low dependency, embeddable HTML/JavaScript Markdown editor.",
5
5
  "main": "lib/index.js",
6
6
  "files": [