UNPKG

6.92 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4/**
5 * Copyright (c) Microsoft Corporation. All rights reserved.
6 * Licensed under the MIT License.
7 */
8const fs = require("fs");
9const path = require("path");
10const CLDebug_1 = require("./CLDebug");
11class TemplateProvider {
12 // TODO: Decouple template renderer from types from Action classes
13 // E.g. use generic key,value object instead of RenderedActionArgument
14 static RenderTemplate(templateName, templateArguments) {
15 return tslib_1.__awaiter(this, void 0, void 0, function* () {
16 let template = this.GetTemplate(templateName);
17 if (template === null) {
18 return null;
19 }
20 let templateString = JSON.stringify(template);
21 let argumentNames = this.GetArgumentNames(templateString);
22 // Substitute argument values
23 for (let argumentName of argumentNames) {
24 let renderedActionArgument = templateArguments.find(a => a.parameter == argumentName);
25 if (renderedActionArgument) {
26 templateString = templateString.replace(new RegExp(`{{${argumentName}}}`, 'g'), renderedActionArgument.value || '');
27 }
28 }
29 templateString = this.RemoveEmptyArguments(templateString);
30 return JSON.parse(templateString);
31 });
32 }
33 static GetTemplates() {
34 let templates = [];
35 let files = this.GetTemplatesNames();
36 for (let file of files) {
37 let fileContent = this.GetTemplate(file);
38 // Clear submit check (will the set by extracting template variables)
39 this.hasSubmitError = false;
40 let tvs = this.UniqueTemplateVariables(fileContent);
41 // Make sure template has submit item
42 let validationError = this.hasSubmitError
43 ? `Template "${file}" has an "Action.Submit" item but no data. Submit item must be of the form: "type": "Action.Submit", "data": string` : null;
44 let templateBody = JSON.stringify(fileContent);
45 let template = {
46 name: file,
47 variables: tvs,
48 body: templateBody,
49 validationError: validationError
50 };
51 templates.push(template);
52 }
53 return templates;
54 }
55 static UniqueTemplateVariables(template) {
56 // Get all template variables
57 let templateVariables = this.GetTemplateVariables(template);
58 // Make entries unique, and use verion with existing type
59 let unique = [];
60 for (let tv of templateVariables) {
61 let existing = unique.find(i => i.key == tv.key);
62 if (existing) {
63 if (existing.type != null && tv.type != null && existing.type != tv.type) {
64 CLDebug_1.CLDebug.Error(`Template variable "${tv.key}" used for two diffent types - "${tv.type}" and "${existing.type}". Ignoring.`);
65 }
66 else {
67 existing.type = existing.type || tv.type;
68 }
69 }
70 else {
71 unique.push(tv);
72 }
73 }
74 return unique;
75 }
76 static RemoveEmptyArguments(formString) {
77 return formString.replace(/{{\s*[\w\.]+\s*}}/g, '');
78 }
79 static GetArgumentNames(formString) {
80 // Get set of unique entities
81 let mustaches = formString.match(/{{\s*[\w\.]+\s*}}/g);
82 if (mustaches) {
83 let entities = [...new Set(mustaches.map(x => x.match(/[\w\.]+/)[0]))];
84 return entities;
85 }
86 return [];
87 }
88 static TemplateDirectory() {
89 //TODO - make this configurable
90 let templateDirectory = path.join(process.cwd(), './cards');
91 // Try up a directory or two as could be in /lib or /dist folder depending on deployment
92 if (!fs.existsSync(templateDirectory)) {
93 templateDirectory = path.join(process.cwd(), '../cards');
94 }
95 if (!fs.existsSync(templateDirectory)) {
96 templateDirectory = path.join(process.cwd(), '../../cards');
97 }
98 return templateDirectory;
99 }
100 static GetTemplate(templateName) {
101 const filename = path.join(this.TemplateDirectory(), `${templateName}.json`);
102 try {
103 const templateString = fs.readFileSync(filename, 'utf-8');
104 try {
105 const template = JSON.parse(templateString);
106 return template;
107 }
108 catch (_a) {
109 CLDebug_1.CLDebug.Error(`Invalid JSON: Failed to Parse template named "${templateName}"`);
110 return null;
111 }
112 }
113 catch (_b) {
114 CLDebug_1.CLDebug.Error(`Can't find template named: "${filename}"`);
115 }
116 }
117 static GetTemplatesNames() {
118 try {
119 let fileNames = fs.readdirSync(this.TemplateDirectory());
120 fileNames = fileNames.filter(fn => fn.endsWith('.json'));
121 let templates = fileNames.map(f => f.slice(0, f.lastIndexOf('.')));
122 return templates;
123 }
124 catch (_a) {
125 CLDebug_1.CLDebug.Log("No Card directory found");
126 return [];
127 }
128 }
129 static GetVarNames(template) {
130 let mustaches = [];
131 for (let i in template) {
132 if (typeof template[i] != 'object') {
133 let searchStr = JSON.stringify(template[i]);
134 let results = searchStr.match(/{{\s*[\w\.]+\s*}}/g);
135 if (results) {
136 mustaches = mustaches.concat(results.map(x => x.match(/[\w\.]+/)[0]));
137 }
138 }
139 }
140 return mustaches;
141 }
142 static GetTemplateVariables(template) {
143 let tvs = [];
144 if (template && template.type === "Action.Submit" && (typeof template.data !== 'string')) {
145 this.hasSubmitError = true;
146 }
147 // Get variable names
148 let vars = this.GetVarNames(template);
149 if (vars.length > 0) {
150 for (let key of vars) {
151 let tv = { key: key, type: template['type'] };
152 tvs.push(tv);
153 }
154 }
155 // Iterate through keys
156 for (let i in template) {
157 if (!template.hasOwnProperty(i)) {
158 continue;
159 }
160 if (template[i] instanceof Array) {
161 for (let item of template[i]) {
162 tvs = tvs.concat(this.GetTemplateVariables(item));
163 }
164 }
165 else if (typeof template[i] == 'object') {
166 tvs = tvs.concat(this.GetTemplateVariables(template[i]));
167 }
168 }
169 return tvs;
170 }
171}
172TemplateProvider.hasSubmitError = false;
173exports.TemplateProvider = TemplateProvider;
174//# sourceMappingURL=TemplateProvider.js.map
\No newline at end of file