Skip to content

Commit d624c90

Browse files
committed
Hidden blocks support
1 parent ede9a44 commit d624c90

File tree

5 files changed

+143
-100
lines changed

5 files changed

+143
-100
lines changed

index.ts

Lines changed: 97 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,59 @@ var yargsModule = require("yargs");
55
var pathModule = require("path");
66
var osModule = require('os');
77

8+
const ws = "[\\t ]*";
9+
const wsAndLine = "[\\r]?[\\n]?";
10+
11+
const expConsts = {
12+
name: "((?:[a-z]+\\-)*[a-z]+)",
13+
hide: "\\(hide\\)" + ws,
14+
start: ">>" + ws,
15+
end: "<<" + ws
16+
}
17+
18+
interface FormatSpec {
19+
commentStart: string;
20+
commentEnd: string;
21+
postProcess?: (string) => string;
22+
}
23+
24+
const jsSpec: FormatSpec = {
25+
commentStart: ws + "\\/\\/" + ws,
26+
commentEnd: wsAndLine
27+
}
28+
29+
const cssSpec: FormatSpec = {
30+
commentStart: ws + "\\/\\*" + ws,
31+
commentEnd: ws + "\\*\\/" + wsAndLine
32+
}
33+
34+
const xmlSpec: FormatSpec = {
35+
commentStart: ws + "<!--" + ws,
36+
commentEnd: ws + "-->" + wsAndLine,
37+
postProcess: function(snippet: string) {
38+
var bindingRegEx = new RegExp("\{\{.*\}\}");
39+
var newLineChar = '\n';
40+
var linesOfSnippet = snippet.split(newLineChar);
41+
var newSnippet = linesOfSnippet.length > 0 ? "" : snippet;
42+
43+
for (var i = 0; i < linesOfSnippet.length; i++) {
44+
var currentLine = linesOfSnippet[i];
45+
var match = bindingRegEx.exec(currentLine);
46+
47+
if (match) {
48+
currentLine = "\{\% raw \%\}" + currentLine + "\{\% endraw \%\}";
49+
}
850

51+
newSnippet += currentLine;
52+
53+
if (i < linesOfSnippet.length - 1) {
54+
newSnippet += newLineChar;
55+
}
56+
}
57+
58+
return newSnippet;
59+
}
60+
}
961
export class SnippetInjector {
1062
private _storedSnippets;
1163
private _snippetTitles: string;
@@ -14,7 +66,8 @@ export class SnippetInjector {
1466
private _storedSourceTypes: Array<string>;
1567
private _storedTargetTypes: Array<string>;
1668
private _storedSourceTitles: any;
17-
private _fileProcessors = {};
69+
70+
private _fileFormatSpecs = {};
1871

1972

2073
constructor() {
@@ -59,12 +112,12 @@ export class SnippetInjector {
59112
}
60113
}
61114

62-
this._fileProcessors['.js'] = this.processTSFileCore;
63-
this._fileProcessors['.ts'] = this.processTSFileCore;
64-
this._fileProcessors['.xml'] = this.processXMLFileCore;
65-
this._fileProcessors['.java'] = this.processTSFileCore;
66-
this._fileProcessors['.cs'] = this.processTSFileCore;
67-
this._fileProcessors['.css'] = this.processCSSFileCore;
115+
this._fileFormatSpecs['.js'] = jsSpec;
116+
this._fileFormatSpecs['.ts'] = jsSpec;
117+
this._fileFormatSpecs['.java'] = jsSpec;
118+
this._fileFormatSpecs['.cs'] = jsSpec;
119+
this._fileFormatSpecs['.xml'] = xmlSpec;
120+
this._fileFormatSpecs['.css'] = cssSpec;
68121
}
69122

70123
/**
@@ -113,7 +166,7 @@ export class SnippetInjector {
113166
private processDocsFile(path: string, extensionFilter: string) {
114167
console.log("Processing docs file: " + path);
115168
var fileContents = fsModule.readFileSync(path, 'utf8');
116-
var regExpOpen = /\<\s*snippet\s+id=\'((?:[a-z]+\-)+[a-z]+)\'\s*\/\s*\>/g;
169+
var regExpOpen = /\<\s*snippet\s+id=\'((?:[a-z]+\-)*[a-z]+)\'\s*\/\s*\>/g;
117170
var match = regExpOpen.exec(fileContents);
118171
var hadMatches: boolean = false;
119172
while (match) {
@@ -162,16 +215,14 @@ export class SnippetInjector {
162215
}
163216

164217
private processFile(path: string, extensionFilter: string) {
165-
var processor = this._fileProcessors[extensionFilter];
166-
processor.call(this, path, extensionFilter);
167-
}
168-
169-
private processTSFileCore(path: string, extensionFilter: string) {
170218
console.log("Processing source file: " + path);
219+
220+
var spec: FormatSpec = this._fileFormatSpecs[extensionFilter];
221+
var regExpOpen = new RegExp(spec.commentStart + expConsts.start + expConsts.name + spec.commentEnd, "g");
222+
var regExpOpenReplacer = new RegExp(spec.commentStart + expConsts.start + expConsts.name + spec.commentEnd, "g");
223+
var regExpCloseReplacer = new RegExp(spec.commentStart + expConsts.end + expConsts.name + spec.commentEnd, "g");
224+
171225
var fileContents = fsModule.readFileSync(path, 'utf8');
172-
var regExpOpen = /\/\/\s*>>\s*(([a-z]+\-)+[a-z]+)\s*/g;
173-
var regExpOpenReplacer = /\/\/\s*>>\s*(?:([a-z]+\-)+[a-z]+)\s+/g;
174-
var regExpCloseReplacer = /\/\/\s*<<\s*(?:([a-z]+\-)+[a-z]+)\s+/g;
175226
var match = regExpOpen.exec(fileContents);
176227
while (match) {
177228
var matchIndex = match.index;
@@ -181,106 +232,57 @@ export class SnippetInjector {
181232
match = regExpOpen.exec(fileContents);
182233
continue;
183234
}
184-
var regExpCurrentClosing = new RegExp("//\\s*<<\\s*" + idOfSnippet);
235+
236+
var regExpCurrentClosing = new RegExp(spec.commentStart + expConsts.end + idOfSnippet + spec.commentEnd);
185237
var closingTagMatch = regExpCurrentClosing.exec(fileContents);
186-
if (!closingTagMatch){
238+
if (!closingTagMatch) {
187239
throw new Error("Closing tag not found for: " + idOfSnippet);
188240
}
189241
var indexOfClosingTag = closingTagMatch.index;
242+
190243
var snippet = fileContents.substr(matchIndex + matchLength, indexOfClosingTag - matchIndex - matchLength);
191244
snippet = snippet.replace(regExpOpenReplacer, "");
192245
snippet = snippet.replace(regExpCloseReplacer, "");
193-
console.log("Snippet resolved: " + snippet);
194-
this._storedSnippets[extensionFilter + idOfSnippet] = snippet;
195-
match = regExpOpen.exec(fileContents);
196-
}
197-
}
198-
199-
private processCSSFileCore(path: string, extensionFilter: string) {
200-
console.log("Processing source file: " + path);
201-
var fileContents = fsModule.readFileSync(path, 'utf8');
202-
203-
var regExpOpen = /\/\*\s*>>\s*(([a-z]+\-)+[a-z]+)\s*\*\//g;
204-
var regExpOpenReplacer = /\/\*\s*>>\s*(?:([a-z]+\-)+[a-z]+)\s+\*\//g;
205-
var regExpCloseReplacer = /\/\*\s*<<\s*(?:([a-z]+\-)+[a-z]+)\s+\*\//g;
206-
var match = regExpOpen.exec(fileContents);
207-
while (match) {
208-
var matchIndex = match.index;
209-
var matchLength = match[0].length;
210-
var idOfSnippet = match[1];
211-
if (this._storedSnippets[extensionFilter + idOfSnippet] !== undefined) {
212-
match = regExpOpen.exec(fileContents);
213-
continue;
214-
}
215-
var regExpCurrentClosing = new RegExp("/\\*\\s*<<\\s*" + idOfSnippet +"\\s+\\*/");
216-
var closingTagMatch = regExpCurrentClosing.exec(fileContents);
217-
if (!closingTagMatch){
218-
throw new Error("Closing tag not found for: " + idOfSnippet);
246+
if (spec.postProcess) {
247+
snippet = spec.postProcess(snippet);
219248
}
220-
var indexOfClosingTag = closingTagMatch.index;
221-
var snippet = fileContents.substr(matchIndex + matchLength, indexOfClosingTag - matchIndex - matchLength);
222-
snippet = snippet.replace(regExpOpenReplacer, "");
223-
snippet = snippet.replace(regExpCloseReplacer, "");
224-
console.log("Snippet resolved: " + snippet);
225-
this._storedSnippets[extensionFilter + idOfSnippet] = snippet;
226-
match = regExpOpen.exec(fileContents);
227-
}
228-
}
229249

230-
private processXMLFileCore(path: string, extensionFilter: string) {
231-
console.log("Processing source file: " + path);
232-
var extname = pathModule.extname(path);
233-
var fileContents = fsModule.readFileSync(path, 'utf8');
234-
var regExpOpen = /<!--\s*>>\s*(([a-z]+\-)+[a-z]+)\s*-->/g;
235-
var regExpOpenReplacer = /<!--\s*>>\s*(?:([a-z]+\-)+[a-z]+)\s+-->/g;
236-
var regExpCloseReplacer = /<!--\s*<<\s*(?:([a-z]+\-)+[a-z]+)\s+-->/g;
237-
var match = regExpOpen.exec(fileContents);
238-
while (match) {
239-
var matchIndex = match.index;
240-
var matchLength = match[0].length;
241-
var idOfSnippet = match[1];
242-
if (this._storedSnippets[extensionFilter + idOfSnippet] !== undefined) {
243-
match = regExpOpen.exec(fileContents);
244-
continue;
245-
}
246-
var regExpCurrentClosing = new RegExp("<!--\\s*<<\\s*" + idOfSnippet + "\\s+-->");
247-
var closingTagMatch = regExpCurrentClosing.exec(fileContents);
248-
if (!closingTagMatch){
249-
throw new Error("Closing tag not found for: " + idOfSnippet);
250-
}
251-
var indexOfClosingTag = closingTagMatch.index;
252-
var snippet = fileContents.substr(matchIndex + matchLength, indexOfClosingTag - matchIndex - matchLength);
253-
snippet = snippet.replace(regExpOpenReplacer, "");
254-
snippet = snippet.replace(regExpCloseReplacer, "");
255-
snippet = this.escapeBindings(snippet);
250+
snippet = this.removeHiddenBlocks(snippet, spec);
251+
256252
console.log("Snippet resolved: " + snippet);
257253
this._storedSnippets[extensionFilter + idOfSnippet] = snippet;
258254
match = regExpOpen.exec(fileContents);
259255
}
260256
}
261257

262-
private escapeBindings(snippet: string) {
263-
var bindingRegEx = new RegExp("\{\{.*\}\}");
264-
var newLineChar = '\n';
265-
var linesOfSnippet = snippet.split(newLineChar);
266-
var newSnippet = linesOfSnippet.length > 0 ? "" : snippet;
258+
private removeHiddenBlocks(snippet: string, spec: FormatSpec) {
259+
const startExp = new RegExp(spec.commentStart + expConsts.start + expConsts.hide + spec.commentEnd, "g");
260+
const endExp = new RegExp(spec.commentStart + expConsts.end + expConsts.hide + spec.commentEnd, "g");
267261

268-
for (var i = 0; i < linesOfSnippet.length; i++) {
269-
var currentLine = linesOfSnippet[i];
270-
var match = bindingRegEx.exec(currentLine);
262+
var match: RegExpMatchArray;
263+
var startMatches = new Array<RegExpMatchArray>();
264+
var endMatches = new Array<RegExpMatchArray>();
271265

272-
if (match) {
273-
currentLine = "\{\% raw \%\}" + currentLine + "\{\% endraw \%\}";
274-
}
266+
while (match = startExp.exec(snippet)) {
267+
startMatches.push(match);
268+
}
275269

276-
newSnippet += currentLine;
270+
while (match = endExp.exec(snippet)) {
271+
endMatches.push(match);
272+
}
277273

278-
if (i < linesOfSnippet.length - 1) {
279-
newSnippet += newLineChar;
280-
}
274+
// Validate
275+
if (startMatches.length !== endMatches.length) {
276+
throw new Error("Start and end match blockes don't match for snippet: " + snippet);
281277
}
282278

283-
return newSnippet;
279+
for (var i = startMatches.length - 1; i >= 0; i--) {
280+
let start = startMatches[i];
281+
let end = endMatches[i];
282+
snippet = snippet.substr(0, start.index) + snippet.substr(end.index + end[0].length);
283+
}
284+
285+
return snippet;
284286
}
285287
}
286288

tests/docsroot/test.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
# XML snippet
22
<snippet id='xml-snippet'/>
33

4+
This one has some hidden parts:
5+
<snippet id='xml-snippet-with-hidden-section'/>
6+
47
# JS/TS snippet:
58
<snippet id='ts-snippet'/>
69

10+
This one has some hidden parts:
11+
<snippet id='ts-snippet-with-hidden-section'/>
12+
13+
714
# CSS snippet:
8-
<snippet id='css-snippet'/>
15+
<snippet id='css-snippet'/>
16+
<snippet id='cssSnippet'/>
17+
18+
This one has some hidden parts:
19+
<snippet id='css-snippet-with-hidden-section'/>

tests/root/test-css.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,12 @@
44
text-align: center;
55
}
66
/* << css-snippet */
7+
8+
/* >> css-snippet-with-hidden-section */
9+
.btn {
10+
color: green;
11+
/* >> (hide) */
12+
visibility: hidden;
13+
/* << (hide) */
14+
}
15+
/* << css-snippet-with-hidden-section */

tests/root/test-ts.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@
22
export function sum(a, b){
33
return a + b;
44
}
5-
// << ts-snippet
5+
// << ts-snippet
6+
7+
// >> ts-snippet-with-hidden-section
8+
export function div(a, b){
9+
// >> (hide)
10+
console.log("You should not see this!")
11+
// << (hide)
12+
return a / b;
13+
}
14+
// << ts-snippet-with-hidden-section

tests/root/test-xml.xml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
<navigation:ExamplePage xmlns:navigation="navigation/example-page" loaded="onPageLoaded" xmlns:lv="nativescript-telerik-ui/listview" xmlns="http://www.nativescript.org/tns.xsd">
2-
<!-- >> xml-snippet -->
32
<StackLayout>
4-
<Label fontSize="20" text="{{ itemName }}"/>
3+
<!-- >> xml-snippet -->
4+
<StackLayout>
5+
<Label fontSize="20" text="{{ itemName }}"/>
6+
</StackLayout>
7+
<!-- << xml-snippet -->
8+
9+
<!-- >> xml-snippet-with-hidden-section -->
10+
<StackLayout>
11+
<!-- >> (hide) -->
12+
<Label text="you should not see this"/>
13+
<!-- << (hide) -->
14+
<Label fontSize="20" text="{{ itemName }}"/>
15+
</StackLayout>
16+
<!-- << xml-snippet-with-hidden-section -->
17+
518
</StackLayout>
6-
<!-- << xml-snippet -->
719
</navigation:ExamplePage>

0 commit comments

Comments
 (0)