diff options
| -rw-r--r-- | docs/spec/ngdocSpec.js | 27 | ||||
| -rw-r--r-- | docs/src/ngdoc.js | 27 | ||||
| -rw-r--r-- | docs/src/templates/doc_widgets.css | 51 | ||||
| -rw-r--r-- | docs/src/templates/doc_widgets.js | 82 | ||||
| -rw-r--r-- | docs/src/templates/docs.js | 18 |
5 files changed, 197 insertions, 8 deletions
diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index 7ad364c0..e4e21e25 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -165,11 +165,38 @@ describe('ngdoc', function(){ '<p>asdf x</p>'); }); + it('should ignore doc widgets', function() { + expect(new Doc().markdown('text<doc:example>do not touch</doc:example>')). + toEqual('<p>text</p><doc:example>do not touch</doc:example>'); + + expect(new Doc().markdown('text<doc:tutorial-instructions>do not touch</doc:tutorial-instructions>')). + toEqual('<p>text</p><doc:tutorial-instructions>do not touch</doc:tutorial-instructions>'); + }); + + it('should ignore doc widgets with params', function() { + expect(new Doc().markdown('text<doc:tutorial-instructions id="10" show="true">do not touch</doc:tutorial-instructions>')). + toEqual('<p>text</p><doc:tutorial-instructions id="10" show="true">do not touch</doc:tutorial-instructions>'); + }); + it('should replace text between two <pre></pre> tags', function() { expect(new Doc().markdown('<pre>x</pre># One<pre>b</pre>')). toMatch('</div><h1>One</h1><div'); }); + it('should ignore nested doc widgets', function() { + expect(new Doc().markdown( + 'before<doc:tutorial-instructions>\n' + + '<doc:tutorial-instruction id="git-mac" name="Git on Mac/Linux">' + + '\ngit bla bla\n</doc:tutorial-instruction>\n' + + '</doc:tutorial-instructions>')).toEqual( + + '<p>before</p><doc:tutorial-instructions>\n' + + '<doc:tutorial-instruction id="git-mac" name="Git on Mac/Linux">\n' + + 'git bla bla\n' + + '</doc:tutorial-instruction>\n' + + '</doc:tutorial-instructions>'); + }); + it('should unindent text before processing based on the second line', function() { expect(new Doc().markdown('first line\n' + ' second line\n\n' + diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index fa3fbdac..61ac6f78 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -78,16 +78,27 @@ Doc.prototype = { }, markdown: function (text) { - var self = this; - var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/; - var IS_ANGULAR = /^angular\./; if (!text) return text; - text = trim(text); + var self = this, + IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/, + IS_ANGULAR = /^angular\./, + parts = trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:(\S*).*?>[\s\S]*?<\/doc:\2>)/); + + parts.forEach(function(text, i) { + + function isDocWidget(name) { + if ((i + 1) % 3 != 2) return false; + if (name) return parts[i+1] == name; + return !!parts[i+1]; + } - var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/); + // ignore each third item which is doc widget tag + if (!((i + 1) % 3)) { + parts[i] = ''; + return; + } - parts.forEach(function(text, i){ if (text.match(/^<pre>/)) { text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){ var clazz = 'brush: js;'; @@ -99,7 +110,7 @@ Doc.prototype = { content.replace(/</g, '<').replace(/>/g, '>') + '</pre></div>'; }); - } else if (text.match(/^<doc:example>/)) { + } else if (isDocWidget('example')) { text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi, function(_, before, content, after){ return '<pre class="doc-source">' + htmlEscape(content) + '</pre>'; @@ -109,7 +120,7 @@ Doc.prototype = { self.scenarios.push(content); return '<pre class="doc-scenario">' + htmlEscape(content) + '</pre>'; }); - } else { + } else if (!isDocWidget()) { text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>'); text = text.replace(/{@link\s+([^\s}]+)\s*([^}]*?)\s*}/g, function(_all, url, title){ diff --git a/docs/src/templates/doc_widgets.css b/docs/src/templates/doc_widgets.css index 9f007f0e..4f759a8b 100644 --- a/docs/src/templates/doc_widgets.css +++ b/docs/src/templates/doc_widgets.css @@ -33,3 +33,54 @@ li.doc-example-live { div.syntaxhighlighter { padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars http://is.gd/gSMgC */ } + +/* TABS - tutorial environment navigation */ + +div.tabs-nav { + height: 25px; + position: relative; +} + +div.tabs-nav ul li { + list-style: none; + display: inline-block; + padding: 5px 10px; +} + +div.tabs-nav ul li.current a { + color: white; + text-decoration: none; +} + +div.tabs-nav ul li.current { + background: #7989D6; + -moz-box-shadow: 4px 4px 6px #48577D; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + box-shadow: 4px 4px 6px #48577D; + border-radius-topright: 8px; + border-radius-topleft: 8px; + -webkit-box-shadow: 4px 4px 6px #48577D; + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + border-top-right-radius: 8px; + border-top-left-radius: 8px; +} + +div.tabs-content { + padding: 4px; + position: relative; + background: #7989D6; + -moz-border-radius: 8px; + border-radius: 8px; + -webkit-border-radius: 8px; +} + +div.tabs-content-inner { + margin: 1px; + padding: 10px; + background: white; + border-radius: 6px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; +} diff --git a/docs/src/templates/doc_widgets.js b/docs/src/templates/doc_widgets.js index 6275012c..a3527c52 100644 --- a/docs/src/templates/doc_widgets.js +++ b/docs/src/templates/doc_widgets.js @@ -85,4 +85,86 @@ return {html: lines.join('\n'), hilite: lineNo.join(',') }; }; + var HTML_TPL = + '<a ng:init="showInstructions = {show}" ng:show="!showInstructions" ng:click="showInstructions = true" href>Show Instructions</a>' + + '<div ng:controller="TutorialInstructionsCtrl" ng:show="showInstructions">' + + '<div class="tabs-nav">' + + '<ul>' + + '</ul>' + + '</div>' + + '<div class="tabs-content"><div class="tabs-content-inner">' + + + '</div></div>' + + '</div>'; + + var HTML_NAV = '<li ng:class="currentCls(\'{id}\')"><a ng:click="select(\'{id}\')" href>{title}</a></li>'; + var HTML_CONTENT = '<div ng:show="selected==\'{id}\'">{content}</div>'; + + var DEFAULT_NAV = + '<li ng:class="currentCls(\'git-mac\')"><a ng:click="select(\'git-mac\')" href>Git on Mac/Linux</a></li>' + + '<li ng:class="currentCls(\'git-win\')"><a ng:click="select(\'git-win\')" href>Git on Windows</a></li>' + + '<li ng:class="currentCls(\'ss-mac\')"><a ng:click="select(\'ss-mac\')" href>Snapshots on Mac/Linux</a></li>' + + '<li ng:class="currentCls(\'ss-win\')"><a ng:click="select(\'ss-win\')" href>Snapshots on Windows</a></li>'; + + var DEFAULT_CONTENT = + '<div ng:show="selected==\'git-mac\'">' + + '<ol>' + + '<li><p>Reset the workspace to step {step}.</p>' + + '<pre><code> git checkout -f step-{step}</code></pre></li>' + + '<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>' + + '</ol>' + + '</div>' + + + '<div ng:show="selected==\'git-win\'">' + + '<ol>' + + '<li><p>Reset the workspace to step {step}.</p>' + + '<pre><code> git checkout -f step-{step}</code></pre></li>' + + '<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>' + + '</ol>' + + '</div>' + + + '<div ng:show="selected==\'ss-mac\'">' + + '<ol>' + + '<li><p>Reset the workspace to step {step}.</p>' + + '<pre><code> ./goto_step.sh {step}</code></pre></li>' + + '<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>' + + '</ol>' + + '</div>' + + + '<div ng:show="selected==\'ss-win\'">' + + '<ol>' + + '<li><p>Reset the workspace to step {step}.</p>' + + '<pre><code> ./goto_step.bat {step}</code></pre></li>' + + '<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>' + + '</ol>' + + '</div>'; + + angular.widget('doc:tutorial-instructions', function(element) { + element.hide(); + this.descend(true); + + var tabs = angular.element(HTML_TPL.replace('{show}', element.attr('show') || 'false')), + nav = tabs.find('.tabs-nav ul'), + content = tabs.find('.tabs-content-inner'), + children = element.children(); + + if (children.length) { + // load custom content + angular.forEach(element.children(), function(elm) { + var elm = angular.element(elm), + id = elm.attr('id'); + + nav.append(HTML_NAV.replace('{title}', elm.attr('title')).replace(/\{id\}/g, id)); + content.append(HTML_CONTENT.replace('{id}', id).replace('{content}', elm.html())); + }); + } else { + // default + nav.append(DEFAULT_NAV); + content.append(DEFAULT_CONTENT.replace(/\{step\}/g, element.attr('step'))); + } + + element.html(''); + element.append(tabs); + element.show(); + }); })(); diff --git a/docs/src/templates/docs.js b/docs/src/templates/docs.js index e05f0ec1..47d294c3 100644 --- a/docs/src/templates/docs.js +++ b/docs/src/templates/docs.js @@ -65,3 +65,21 @@ angular.widget('code', function(element){ SyntaxHighlighter['defaults'].toolbar = false; SyntaxHighlighter['defaults'].gutter = false; + +/** + * Controller for tutorial instructions + * @param $cookieStore + * @constructor + */ +function TutorialInstructionsCtrl($cookieStore) { + this.selected = $cookieStore.get('selEnv') || 'git-mac'; + + this.currentCls = function(id, cls) { + return this.selected == id ? cls || 'current' : ''; + }; + + this.select = function(id) { + this.selected = id; + $cookieStore.put('selEnv', id); + }; +} |
