summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/static_site_editor/services/parse_source_file.js
blob: 126dfe81b9094eb11dc990037af27947f5b01eba (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
const parseSourceFile = raw => {
  const frontMatterRegex = /(^---$[\s\S]*?^---$)/m;
  const preGroupedRegex = /([\s\S]*?)(^---$[\s\S]*?^---$)(\s*)([\s\S]*)/m; // preFrontMatter, frontMatter, spacing, and content
  let initial;
  let editable;

  const hasFrontMatter = source => frontMatterRegex.test(source);

  const buildPayload = (source, header, spacing, body) => {
    return { raw: source, header, spacing, body };
  };

  const parse = source => {
    if (hasFrontMatter(source)) {
      const match = source.match(preGroupedRegex);
      const [, preFrontMatter, frontMatter, spacing, content] = match;
      const header = preFrontMatter + frontMatter;

      return buildPayload(source, header, spacing, content);
    }

    return buildPayload(source, '', '', source);
  };

  const syncEditable = () => {
    /*
    We re-parse as markdown editing could have added non-body changes (preFrontMatter, frontMatter, or spacing).
    Re-parsing additionally gets us the desired body that was extracted from the potentially mutated editable.raw
    */
    editable = parse(editable.raw);
  };

  const syncBodyToRaw = () => {
    editable.raw = `${editable.header}${editable.spacing}${editable.body}`;
  };

  const sync = (newVal, isBodyToRaw) => {
    const editableKey = isBodyToRaw ? 'body' : 'raw';
    editable[editableKey] = newVal;

    if (isBodyToRaw) {
      syncBodyToRaw();
    }

    syncEditable();
  };

  const content = (isBody = false) => {
    const editableKey = isBody ? 'body' : 'raw';
    return editable[editableKey];
  };

  const isModified = () => initial.raw !== editable.raw;

  initial = parse(raw);
  editable = parse(raw);

  return {
    content,
    isModified,
    sync,
  };
};

export default parseSourceFile;