Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,42 @@ Use the `<snippet id='<your-snippet-id>'/>` notation to define the corresponding
<snippet id='sum-snippet'/>
```

If you set `-w` flag your snippets will be wrapped around the snippet notation you have been provided. This way when you update your snipet source - the `markdown-snippet-injector` will reflect the changes in your markdown as well.

Example:

`mdinject -w --root=<path-to-source-code> --docsroot=<path-to-docs>`

main.css
```
/* >> css-snippet */
.btn {
color: green;
text-align: center;
}
/* << css-snippet */
```

README.MD
```
This is a CSS snippet
<snippet id='css-snippet'/>
```

After first build the README.MD will looks like:
```
This is a CSS snippet
<snippet id='css-snippet'>
```
.btn {
color: green;
text-align: center;
}
```
</snippet>
```
Then when you update `main.css`, your README.MD will be updated as well.

# Advanced features
## Nested snippets
Nested snippets are also supported. This is helpful in scenarios where you want to explain parts of a larger snippet in steps:
Expand Down Expand Up @@ -162,12 +198,11 @@ When injected, a snippet is formatted using the default MarkDown code-snippet fo
```
mdinject --root=. --docsroot=../ --sourceext=".java|.cs" --targetext=".md|.txt" --snippettitles="Java|C#"
```
> Note that the order of the snippet titles must be the related to the order of the source extension types so that they match.

## Run e2e tests
1. Clone repo
2. npm install
3. npm test

E2E tests are developed with [Mocha](https://mochajs.org).

> Note that the order of the snippet titles must be the related to the order of the source extension types so that they match.
2 changes: 2 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ if (docsRoot === undefined) {
}

var snippetInjector = new SnippetInjector();

snippetInjector.toWrap = yargsModule.argv.w;
snippetInjector.sourceFileExtensionFilter = yargsModule.argv.sourceext || ".ts";
snippetInjector.targetFileExtensionFilter = yargsModule.argv.targetext || ".md";

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"scripts": {
"prepublish": "tsc -p .",
"test": "mocha"
"test": "tsc && mocha"
},
"keywords": [
"markdown",
Expand Down
52 changes: 50 additions & 2 deletions snippet-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const cssSpec: FormatSpec = {
const xmlSpec: FormatSpec = {
commentStart: ws + "<!--" + ws,
commentEnd: ws + "-->" + wsAndLine,
postProcess: function(snippet: string) {
postProcess: function (snippet: string) {
var bindingRegEx = new RegExp("\{\{.*\}\}");
var newLineChar = '\n';
var linesOfSnippet = snippet.split(newLineChar);
Expand Down Expand Up @@ -67,6 +67,7 @@ export class SnippetInjector {
private _storedSourceTypes: Array<string>;
private _storedTargetTypes: Array<string>;
private _storedSourceTitles: any;
private _toWrap: boolean;

private _fileFormatSpecs = {};

Expand All @@ -75,6 +76,14 @@ export class SnippetInjector {
this._storedSnippets = {};
}

get toWrap(): boolean {
return this._toWrap;
}

set toWrap(value: boolean){
this._toWrap = value;
}

get targetFileExtensionFilter(): string {
return this._targetFileExtensionFilter;
}
Expand Down Expand Up @@ -112,7 +121,7 @@ export class SnippetInjector {
this._storedSourceTitles[this._storedSourceTypes[i]] = (currentTitles[i] || "")
}
}

this._fileFormatSpecs['.cs'] = jsSpec;
this._fileFormatSpecs['.swift'] = jsSpec;
this._fileFormatSpecs['.h'] = jsSpec;
Expand Down Expand Up @@ -172,9 +181,25 @@ export class SnippetInjector {
}
}

private replaceWrappedSnippetsWithCorespondingTags(fileContent): string {
var content = "";
content = fileContent.replace(/\<snippet id=['"]([a-zA-Z0-9\-]+)[\S\s]>[\S\s]*?<\/snippet>/g, "<snippet id='$1'/>");
return content;
}

private wrapSnippetWithComments(snippetTag, snippetId): string {
var wrappedSnippetTag = "";
wrappedSnippetTag += "\n<snippet id='" + snippetId + "'>\n"
wrappedSnippetTag += snippetTag
wrappedSnippetTag += "\n</snippet>\n"

return wrappedSnippetTag;
}

private processDocsFile(path: string, extensionFilter: string) {
console.log("Processing docs file: " + path);
var fileContents = fsModule.readFileSync(path, 'utf8');
fileContents = this.replaceWrappedSnippetsWithCorespondingTags(fileContents);
var regExpOpen = /\<\s*snippet\s+id=\'((?:[a-z]+\-)*[a-z]+)\'\s*\/\s*\>/g;
var match = regExpOpen.exec(fileContents);
var hadMatches: boolean = false;
Expand All @@ -197,6 +222,29 @@ export class SnippetInjector {
}

if (finalSnippet.length > 0) {
/*
Check whether it should be wrapped or replaced.
If the tag is closed it will be replaced by the snippet.

From:
<snippet id="snippetId"/>
To:
{your_snippet}

If there is open and closed tag the snippet will be wrapped around snippet tag.

From:
<snippet id="snippetId"></snippet>
To:
<snippet id="snippetId">
{your_snippet}
</snippet>

*/
if (this.toWrap) {
var tmpMatchedString = this.wrapSnippetWithComments(matchedString, placeholderId);
fileContents = fileContents.replace(matchedString, tmpMatchedString);
}
fileContents = fileContents.replace(matchedString, finalSnippet);
console.log("Token replaced: " + matchedString);
}
Expand Down
11 changes: 10 additions & 1 deletion test/docsroot/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@ This one has some hidden parts:
This one has some hidden parts:
<snippet id='ts-snippet-with-hidden-section'/>


# CSS snippet:
<snippet id='css-snippet'/>
<snippet id='cssSnippet'/>

This one has some hidden parts:
<snippet id='css-snippet-with-hidden-section'/>

This one is already processed snippet
<snippet id='css-already-processed'>
```
.btn {
color: green;
background-color: blue;
}
```
</snippet>
111 changes: 93 additions & 18 deletions test/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,112 @@ function hasPattern(pattern, shouldExists, callback) {
} else {
callback(shouldExists ? null : 'Pattern ' + pattern + ' WAS found. This is NOT expected.');
}

}
});
}

function contain(pattern, callback) {
hasPattern(pattern, true, callback);
}

function notContain(pattern, callback) {
hasPattern(pattern, false, callback);
}

describe('markdown-snippet-injector', function () {

beforeEach(function (done) {
preparedemo();
done();
});

//TODO: Add tests for hidden fields
describe('XML',
function () {
it('should process XML snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".xml"');
notContain("<snippet id='xml-snippet'/>", function () {
notContain("<snippet id='xml-snippet'>", function () {
contain('<Label fontSize="20" text="{{ itemName }}"/>', done);
});
});
});

it('should process XML snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".xml"');
hasPattern("<snippet id='xml-snippet'/>", false, done);
});
it('should process XML snippets and wrap it', function (done) {
shelljs.exec('node index.js -w --root=./test/root --docsroot=./test/docsroot-output --sourceext=".xml"');
notContain("<snippet id='xml-snippet'/>", function () {
contain("<snippet id='xml-snippet'>", function () {
contain('<Label fontSize="20" text="{{ itemName }}"/>', done);
});
});
});
});

it('should process TypeScript snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".ts"');
hasPattern("<snippet id='ts-snippet'/>", false, done);
});
describe('TypeScript',
function () {
it('should process TypeScript snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".ts"');
notContain("<snippet id='ts-snippet'/>", function () {
notContain("<snippet id='ts-snippet'>", function () {
notContain("</snippet>", function () {
contain('return a + b;', done);
});
});
});
});

it('should process CSS snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
hasPattern("<snippet id='css-snippet'/>", false, done);
});
it('should process TypeScript snippets and wrap', function (done) {
shelljs.exec('node index.js -w --root=./test/root --docsroot=./test/docsroot-output --sourceext=".ts"');
notContain("<snippet id='ts-snippet'/>", function () {
contain("<snippet id='ts-snippet'>", function () {
contain("</snippet>", done);
});
});
});
});

it('should NOT process snippetIds that are not defined in source', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
hasPattern("<snippet id='cssSnippet'/>", true, done);
});
describe('CSS',
function () {
it('should process CSS snippets', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
notContain("<snippet id='css-snippet'/>", function () {
notContain("<snippet id='css-snippet'>", function () {
notContain("</snippet>", function () {
contain('text-align: center;', done);
});
});
});
});

it('should process CSS snippets and wrap', function (done) {
shelljs.exec('node index.js -w --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
notContain("<snippet id='css-snippet'/>", function () {
contain("<snippet id='css-snippet'>", function () {
contain("</snippet>", function () {
contain('text-align: center;', done);
});
});
});
});

it('should keep hidden the marked area in CSS', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
notContain("visibility: hidden;", done);
});

it('should NOT process snippetIds that are not defined in source', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
contain("<snippet id='cssSnippet'/>", function () {
notContain("<snippet id='cssSnippet'>", done);
});
});

it('should update the already processed snippet tags', function (done) {
shelljs.exec('node index.js --root=./test/root --docsroot=./test/docsroot-output --sourceext=".css"');
contain("<snippet id='css-already-processed'>", function () {
contain("</snippet>", function () {
contain("color: red;", done);
});
});
});
});
});
13 changes: 12 additions & 1 deletion test/root/test-css.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,19 @@
/* >> css-snippet-with-hidden-section */
.btn {
color: green;
background-color: blue;
/* >> (hide) */
visibility: hidden;
/* << (hide) */
}
/* << css-snippet-with-hidden-section */
/* << css-snippet-with-hidden-section */

/* >> css-already-processed */
.text {
color: red;
font-size: 10px;
/* >> (hide) */
visibility: hidden;
/* << (hide) */
}
/* << css-already-processed */
15 changes: 8 additions & 7 deletions test/root/test-xml.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<navigation:ExamplePage xmlns:navigation="navigation/example-page" loaded="onPageLoaded" xmlns:lv="nativescript-telerik-ui/listview" xmlns="http://www.nativescript.org/tns.xsd">
<navigation:ExamplePage
xmlns:navigation="navigation/example-page" loaded="onPageLoaded"
xmlns:lv="nativescript-telerik-ui/listview"
xmlns="http://www.nativescript.org/tns.xsd">
<StackLayout>
<!-- >> xml-snippet -->
<!-- >> xml-snippet -->
<StackLayout>
<Label fontSize="20" text="{{ itemName }}"/>
</StackLayout>
<!-- << xml-snippet -->

<!-- >> xml-snippet-with-hidden-section -->
<!-- << xml-snippet -->
<!-- >> xml-snippet-with-hidden-section -->
<StackLayout>
<!-- >> (hide) -->
<Label text="you should not see this"/>
<!-- << (hide) -->
<Label fontSize="20" text="{{ itemName }}"/>
</StackLayout>
<!-- << xml-snippet-with-hidden-section -->

<!-- << xml-snippet-with-hidden-section -->
</StackLayout>
</navigation:ExamplePage>