aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Markdown/Paragraph.tsx
blob: 5ecedfce14fff877407f70a29bc7297a5ce3c1b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import React from 'react';

interface PropTypes {
  data: string;
}

type RuleName = 'bold' | 'italic' | 'inlineCode' | 'strikeThrough';

interface RuleProperties {
  enclosure: string;
  style: React.CSSProperties;
  pattern?: RegExp;
}

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 capture = (enclosure: string): RegExp => {
  return new RegExp(enclosure + '([^' + enclosure + ']+)' + enclosure);
}
const captureSplit = (enclosure: string): string => {
  return '(' + enclosure + '[^' + enclosure + ']+' + enclosure + ')';
}

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;
  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 }) => {
  const result = data.split(splitter).map(span => <SyntaxSpan data={span} />);
  return <p> {result} </p>;
}

export default Paragraph;