1 | const fs = require("fs");
|
2 | const sections = require("./sections.js");
|
3 | const { REQ, OPT, SKP } = require("./flags.js");
|
4 |
|
5 | function Parser(options, tn, fpth) {
|
6 | this.options = options;
|
7 | this.fpth = fpth;
|
8 | this.obj = {
|
9 | NAME: [tn],
|
10 | PATH: [fpth]
|
11 | };
|
12 | if (options.update || options.style) {
|
13 | this.testtype = "style";
|
14 | } else {
|
15 | this.testtype = "processor";
|
16 | }
|
17 | this.section = false;
|
18 | this.state = null;
|
19 | this.openRex = new RegExp("^.*>>===*\\s(" + Object.keys(sections).join("|") + ")\\s.*=>>.*");
|
20 | this.closeRex = new RegExp("^.*<<===*\\s(" + Object.keys(sections).join("|") + ")\\s.*=<<.*");
|
21 | this.dumpObj = function() {
|
22 | for (var key in this.obj) {
|
23 | this.obj[key] = this.obj[key].join("\n");
|
24 | if (sections[key].type === "json") {
|
25 | try {
|
26 | this.obj[key] = JSON.parse(this.obj[key]);
|
27 | } catch (err) {
|
28 | console.log(this.fpth);
|
29 | throw new Error("JSON parse fail for tag \"" + key + "\"");
|
30 | }
|
31 | }
|
32 | if (sections[key].type === "array") {
|
33 | try {
|
34 | this.obj[key] = this.obj[key].split(/\s*,\s*/);
|
35 | } catch (err) {
|
36 | console.log(this.fpth);
|
37 | throw new Error("Array split fail for tag \"" + key + "\"");
|
38 | }
|
39 | }
|
40 | }
|
41 |
|
42 | for (var key of Object.keys(sections)
|
43 | .filter(key => sections[key][this.testtype] === REQ || sections[key][this.testtype] === OPT)) {
|
44 | if (this.options.watch && key === "CSL") {
|
45 | var inStyle = false;
|
46 | this.obj[key] = fs.readFileSync(this.options.watch[0]).toString();
|
47 | var cslList = this.obj[key].split(/(?:\r\n|\n)/);
|
48 | for (var i in cslList) {
|
49 | var line = cslList[i];
|
50 | if (line.indexOf("<style") > -1) {
|
51 | inStyle = true;
|
52 | }
|
53 | if (inStyle) {
|
54 | var m = line.match(/default-locale=[\"\']([^\"\']+)[\"\']/);
|
55 | if (m && m[1].indexOf("-x-") === -1) {
|
56 | var defaultLocale = m[1] + "-x-sort-en";
|
57 | cslList[i] = cslList[i].replace(/default-locale=[\"\']([^\"\']+)[\"\']/, "default-locale=\"" + defaultLocale + "\"");
|
58 | this.obj.CSL = cslList.join("\n");
|
59 | }
|
60 | }
|
61 | if (inStyle && line.indexOf(">") > -1) {
|
62 | break;
|
63 | }
|
64 | }
|
65 | }
|
66 | if (sections[key][this.testtype] === REQ && "undefined" === typeof this.obj[key]) {
|
67 | console.log(this.fpth);
|
68 | throw new Error("Missing required tag \"" + key + "\"");
|
69 | }
|
70 | }
|
71 | return this.obj;
|
72 | };
|
73 | this.checkLine = function (line) {
|
74 | var m = null;
|
75 | if (this.openRex.test(line)) {
|
76 | m = this.openRex.exec(line);
|
77 | if (this.state) {
|
78 | console.log(this.fpth);
|
79 | throw new Error("Attempted to open tag \"" + m[1] + "\" before tag \"" + this.section + "\" was closed.");
|
80 | }
|
81 | this.section = m[1];
|
82 | this.state = "opening";
|
83 | } else if (this.closeRex.test(line)) {
|
84 | m = this.closeRex.exec(line);
|
85 | if (this.section !== m[1]) {
|
86 | console.log(this.fpth);
|
87 | throw new Error("Expected closing tag \"" + this.section + "\" but found \"" + m[1] + "\"");
|
88 | }
|
89 | this.state = "closing";
|
90 |
|
91 | if (this.section === "RESULT" && !this.obj[this.section]) {
|
92 | this.obj[this.section] = [""];
|
93 | }
|
94 | } else {
|
95 | if (this.state === "opening") {
|
96 | this.obj[this.section] = [];
|
97 | this.state = "reading";
|
98 | } else if (this.state === "closing") {
|
99 | this.state = null;
|
100 | }
|
101 | }
|
102 | if (this.state === "reading") {
|
103 | this.obj[this.section].push(line);
|
104 | }
|
105 | };
|
106 | }
|
107 |
|
108 | function parseFixture(options, tn, fpth) {
|
109 | var raw = fs.readFileSync(fpth).toString();
|
110 | var parser = new Parser(options, tn, fpth);
|
111 | for (var line of raw.split(/(?:\r\n|\n)/)) {
|
112 | parser.checkLine(line);
|
113 | }
|
114 | var ret = parser.dumpObj();
|
115 | return ret;
|
116 | }
|
117 |
|
118 | module.exports = {
|
119 | parseFixture: parseFixture
|
120 | }
|