From 208322f596240d23ff8248733f4b196c1baf8a5a Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sun, 5 Apr 2020 02:35:03 +0300
Subject: feat: parse all inline styles

---
 src/lib/Markdown/Paragraph.tsx | 81 +++++++++++++++++++++---------------------
 1 file changed, 41 insertions(+), 40 deletions(-)

(limited to 'src/lib/Markdown/Paragraph.tsx')

diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx
index f433cf5..5ecedfc 100644
--- a/src/lib/Markdown/Paragraph.tsx
+++ b/src/lib/Markdown/Paragraph.tsx
@@ -4,62 +4,63 @@ interface PropTypes {
   data: string;
 }
 
-interface Closures {
-  [key: string]: string;
-}
+type RuleName = 'bold' | 'italic' | 'inlineCode' | 'strikeThrough';
 
-interface Patterns {
-  [key: string]: RegExp;
+interface RuleProperties {
+  enclosure: string;
+  style: React.CSSProperties;
+  pattern?: RegExp;
 }
 
-interface Styles {
-  [key: string]: React.CSSProperties;
-}
+const rules: Record<RuleName, RuleProperties>= {  // Order matters - lowest property has highest priority
+  strikeThrough: {
+    enclosure: '~~',
+    style: { textDecoration: 'line-through' },
+  },
+  inlineCode: {
+    enclosure: '`',
+    style: { background: '#444444', padding: '4px' },
+  },
+  italic: {
+    enclosure: '\\*',
+    style: { fontStyle: 'italic' },
+  },
+  bold: {
+    enclosure: '\\*\\*',
+    style: { fontWeight: 'bold' },
+  },
+};
 
+const ruleNames = Object.keys(rules) as RuleName[];
 
-const captureInside = (closure: string): any => {
-  return new RegExp(closure + '([^' + closure + ']+)' + closure);
+const capture = (enclosure: string): RegExp => {
+  return new RegExp(enclosure + '([^' + enclosure + ']+)' + enclosure);
 }
-const capture = (closure: string): any => {
-  return new RegExp('(' + closure + '[^' + closure + ']+' + closure + ')');
+const captureSplit = (enclosure: string): string => {
+  return '(' + enclosure + '[^' + enclosure + ']+' + enclosure + ')';
 }
 
-const closures: Closures = {
-  inlineCode: '`',
-  bold: '\\*\\*',
-};
-
-const styles: Styles = {
-  inlineCode: { background: '#444444', padding: '4px' },
-  bold: { fontWeight: 'bold' },
-};
-const patterns: Patterns = {};
-
-
-Object.keys(closures).forEach((key: string): void => {
-  patterns[key] = capture(closures[key]);
-});
-
-const matcher = new RegExp(Object.values(patterns).map(regex => regex.source).join('|'));
-
-Object.keys(closures).forEach((key: string): void => {
-  patterns[key] = captureInside(closures[key]);
+const ruleSplitPatterns: string[] = [];
+ruleNames.forEach(name => {
+  rules[name].pattern = capture(rules[name].enclosure);
+  ruleSplitPatterns.push(captureSplit(rules[name].enclosure));
 });
 
+const splitter = new RegExp(ruleSplitPatterns.join('|'));
 
 const SyntaxSpan: React.FC<PropTypes> = ({ data }) => {
   if (!data) return null;
-  for (let key in styles) {
-    const match = data.match(patterns[key]);
-    if (match) return <span style={styles[key]}>{match[1]}</span>;
-  };
-  return <>{data}</>;
+  let span = <>{data}</>;
+  ruleNames.forEach(name => {
+    const rule = rules[name];
+    const match = data.match(rule.pattern || '');
+    if (match) span = <span style={rule.style}>{match[1]}</span>;
+  });
+  return span;
 }
 
 const Paragraph: React.FC<PropTypes> = ({ data }) => {
-  let result;
-  result = data.split(matcher);
-  result = result.map(span => <SyntaxSpan data={span} />);
+  const result = data.split(splitter).map(span => <SyntaxSpan data={span} />);
   return <p> {result} </p>;
 }
 
-- 
cgit v1.2.3

