Skip to content

Commit 2da0712

Browse files
Vojta JinaIgorMinar
authored andcommitted
Add doc:tutorial-instructions widget
1 parent d05e839 commit 2da0712

5 files changed

Lines changed: 197 additions & 8 deletions

File tree

docs/spec/ngdocSpec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,38 @@ describe('ngdoc', function(){
165165
'<p>asdf x</p>');
166166
});
167167

168+
it('should ignore doc widgets', function() {
169+
expect(new Doc().markdown('text<doc:example>do not touch</doc:example>')).
170+
toEqual('<p>text</p><doc:example>do not touch</doc:example>');
171+
172+
expect(new Doc().markdown('text<doc:tutorial-instructions>do not touch</doc:tutorial-instructions>')).
173+
toEqual('<p>text</p><doc:tutorial-instructions>do not touch</doc:tutorial-instructions>');
174+
});
175+
176+
it('should ignore doc widgets with params', function() {
177+
expect(new Doc().markdown('text<doc:tutorial-instructions id="10" show="true">do not touch</doc:tutorial-instructions>')).
178+
toEqual('<p>text</p><doc:tutorial-instructions id="10" show="true">do not touch</doc:tutorial-instructions>');
179+
});
180+
168181
it('should replace text between two <pre></pre> tags', function() {
169182
expect(new Doc().markdown('<pre>x</pre># One<pre>b</pre>')).
170183
toMatch('</div><h1>One</h1><div');
171184
});
172185

186+
it('should ignore nested doc widgets', function() {
187+
expect(new Doc().markdown(
188+
'before<doc:tutorial-instructions>\n' +
189+
'<doc:tutorial-instruction id="git-mac" name="Git on Mac/Linux">' +
190+
'\ngit bla bla\n</doc:tutorial-instruction>\n' +
191+
'</doc:tutorial-instructions>')).toEqual(
192+
193+
'<p>before</p><doc:tutorial-instructions>\n' +
194+
'<doc:tutorial-instruction id="git-mac" name="Git on Mac/Linux">\n' +
195+
'git bla bla\n' +
196+
'</doc:tutorial-instruction>\n' +
197+
'</doc:tutorial-instructions>');
198+
});
199+
173200
it('should unindent text before processing based on the second line', function() {
174201
expect(new Doc().markdown('first line\n' +
175202
' second line\n\n' +

docs/src/ngdoc.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,27 @@ Doc.prototype = {
7878
},
7979

8080
markdown: function (text) {
81-
var self = this;
82-
var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/;
83-
var IS_ANGULAR = /^angular\./;
8481
if (!text) return text;
8582

86-
text = trim(text);
83+
var self = this,
84+
IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/,
85+
IS_ANGULAR = /^angular\./,
86+
parts = trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:(\S*).*?>[\s\S]*?<\/doc:\2>)/);
87+
88+
parts.forEach(function(text, i) {
89+
90+
function isDocWidget(name) {
91+
if ((i + 1) % 3 != 2) return false;
92+
if (name) return parts[i+1] == name;
93+
return !!parts[i+1];
94+
}
8795

88-
var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/);
96+
// ignore each third item which is doc widget tag
97+
if (!((i + 1) % 3)) {
98+
parts[i] = '';
99+
return;
100+
}
89101

90-
parts.forEach(function(text, i){
91102
if (text.match(/^<pre>/)) {
92103
text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){
93104
var clazz = 'brush: js;';
@@ -99,7 +110,7 @@ Doc.prototype = {
99110
content.replace(/</g, '&lt;').replace(/>/g, '&gt;') +
100111
'</pre></div>';
101112
});
102-
} else if (text.match(/^<doc:example>/)) {
113+
} else if (isDocWidget('example')) {
103114
text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi,
104115
function(_, before, content, after){
105116
return '<pre class="doc-source">' + htmlEscape(content) + '</pre>';
@@ -109,7 +120,7 @@ Doc.prototype = {
109120
self.scenarios.push(content);
110121
return '<pre class="doc-scenario">' + htmlEscape(content) + '</pre>';
111122
});
112-
} else {
123+
} else if (!isDocWidget()) {
113124
text = text.replace(/<angular\/>/gm, '<tt>&lt;angular/&gt;</tt>');
114125
text = text.replace(/{@link\s+([^\s}]+)\s*([^}]*?)\s*}/g,
115126
function(_all, url, title){

docs/src/templates/doc_widgets.css

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,54 @@ li.doc-example-live {
3333
div.syntaxhighlighter {
3434
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars http://is.gd/gSMgC */
3535
}
36+
37+
/* TABS - tutorial environment navigation */
38+
39+
div.tabs-nav {
40+
height: 25px;
41+
position: relative;
42+
}
43+
44+
div.tabs-nav ul li {
45+
list-style: none;
46+
display: inline-block;
47+
padding: 5px 10px;
48+
}
49+
50+
div.tabs-nav ul li.current a {
51+
color: white;
52+
text-decoration: none;
53+
}
54+
55+
div.tabs-nav ul li.current {
56+
background: #7989D6;
57+
-moz-box-shadow: 4px 4px 6px #48577D;
58+
-moz-border-radius-topright: 8px;
59+
-moz-border-radius-topleft: 8px;
60+
box-shadow: 4px 4px 6px #48577D;
61+
border-radius-topright: 8px;
62+
border-radius-topleft: 8px;
63+
-webkit-box-shadow: 4px 4px 6px #48577D;
64+
-webkit-border-top-right-radius: 8px;
65+
-webkit-border-top-left-radius: 8px;
66+
border-top-right-radius: 8px;
67+
border-top-left-radius: 8px;
68+
}
69+
70+
div.tabs-content {
71+
padding: 4px;
72+
position: relative;
73+
background: #7989D6;
74+
-moz-border-radius: 8px;
75+
border-radius: 8px;
76+
-webkit-border-radius: 8px;
77+
}
78+
79+
div.tabs-content-inner {
80+
margin: 1px;
81+
padding: 10px;
82+
background: white;
83+
border-radius: 6px;
84+
-moz-border-radius: 6px;
85+
-webkit-border-radius: 6px;
86+
}

docs/src/templates/doc_widgets.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,86 @@
8585
return {html: lines.join('\n'), hilite: lineNo.join(',') };
8686
};
8787

88+
var HTML_TPL =
89+
'<a ng:init="showInstructions = {show}" ng:show="!showInstructions" ng:click="showInstructions = true" href>Show Instructions</a>' +
90+
'<div ng:controller="TutorialInstructionsCtrl" ng:show="showInstructions">' +
91+
'<div class="tabs-nav">' +
92+
'<ul>' +
93+
'</ul>' +
94+
'</div>' +
95+
'<div class="tabs-content"><div class="tabs-content-inner">' +
96+
97+
'</div></div>' +
98+
'</div>';
99+
100+
var HTML_NAV = '<li ng:class="currentCls(\'{id}\')"><a ng:click="select(\'{id}\')" href>{title}</a></li>';
101+
var HTML_CONTENT = '<div ng:show="selected==\'{id}\'">{content}</div>';
102+
103+
var DEFAULT_NAV =
104+
'<li ng:class="currentCls(\'git-mac\')"><a ng:click="select(\'git-mac\')" href>Git on Mac/Linux</a></li>' +
105+
'<li ng:class="currentCls(\'git-win\')"><a ng:click="select(\'git-win\')" href>Git on Windows</a></li>' +
106+
'<li ng:class="currentCls(\'ss-mac\')"><a ng:click="select(\'ss-mac\')" href>Snapshots on Mac/Linux</a></li>' +
107+
'<li ng:class="currentCls(\'ss-win\')"><a ng:click="select(\'ss-win\')" href>Snapshots on Windows</a></li>';
108+
109+
var DEFAULT_CONTENT =
110+
'<div ng:show="selected==\'git-mac\'">' +
111+
'<ol>' +
112+
'<li><p>Reset the workspace to step {step}.</p>' +
113+
'<pre><code> git checkout -f step-{step}</code></pre></li>' +
114+
'<li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-{step}/app">anglar\'s server</a>.</p></li>' +
115+
'</ol>' +
116+
'</div>' +
117+
118+
'<div ng:show="selected==\'git-win\'">' +
119+
'<ol>' +
120+
'<li><p>Reset the workspace to step {step}.</p>' +
121+
'<pre><code> git checkout -f step-{step}</code></pre></li>' +
122+
'<li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-{step}/app">anglar\'s server</a>.</p></li>' +
123+
'</ol>' +
124+
'</div>' +
125+
126+
'<div ng:show="selected==\'ss-mac\'">' +
127+
'<ol>' +
128+
'<li><p>Reset the workspace to step {step}.</p>' +
129+
'<pre><code> ./goto_step.sh {step}</code></pre></li>' +
130+
'<li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-{step}/app">anglar\'s server</a>.</p></li>' +
131+
'</ol>' +
132+
'</div>' +
133+
134+
'<div ng:show="selected==\'ss-win\'">' +
135+
'<ol>' +
136+
'<li><p>Reset the workspace to step {step}.</p>' +
137+
'<pre><code> ./goto_step.bat {step}</code></pre></li>' +
138+
'<li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-{step}/app">anglar\'s server</a>.</p></li>' +
139+
'</ol>' +
140+
'</div>';
141+
142+
angular.widget('doc:tutorial-instructions', function(element) {
143+
element.hide();
144+
this.descend(true);
145+
146+
var tabs = angular.element(HTML_TPL.replace('{show}', element.attr('show') || 'false')),
147+
nav = tabs.find('.tabs-nav ul'),
148+
content = tabs.find('.tabs-content-inner'),
149+
children = element.children();
150+
151+
if (children.length) {
152+
// load custom content
153+
angular.forEach(element.children(), function(elm) {
154+
var elm = angular.element(elm),
155+
id = elm.attr('id');
156+
157+
nav.append(HTML_NAV.replace('{title}', elm.attr('title')).replace(/\{id\}/g, id));
158+
content.append(HTML_CONTENT.replace('{id}', id).replace('{content}', elm.html()));
159+
});
160+
} else {
161+
// default
162+
nav.append(DEFAULT_NAV);
163+
content.append(DEFAULT_CONTENT.replace(/\{step\}/g, element.attr('step')));
164+
}
165+
166+
element.html('');
167+
element.append(tabs);
168+
element.show();
169+
});
88170
})();

docs/src/templates/docs.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,21 @@ angular.widget('code', function(element){
6565

6666
SyntaxHighlighter['defaults'].toolbar = false;
6767
SyntaxHighlighter['defaults'].gutter = false;
68+
69+
/**
70+
* Controller for tutorial instructions
71+
* @param $cookieStore
72+
* @constructor
73+
*/
74+
function TutorialInstructionsCtrl($cookieStore) {
75+
this.selected = $cookieStore.get('selEnv') || 'git-mac';
76+
77+
this.currentCls = function(id, cls) {
78+
return this.selected == id ? cls || 'current' : '';
79+
};
80+
81+
this.select = function(id) {
82+
this.selected = id;
83+
$cookieStore.put('selEnv', id);
84+
};
85+
}

0 commit comments

Comments
 (0)