From c69921c3a9e92665cac3cbaa4ab216076e8313b4 Mon Sep 17 00:00:00 2001 From: Juliano Date: Mon, 17 Jul 2017 09:29:31 -0300 Subject: [PATCH] fix #5568 and #5793 --- src/lib/expansion/expansion.md | 79 +++++++++++++++++++ src/lib/icon/icon-registry.ts | 4 +- .../expansion-overview-example.css | 1 + .../expansion-overview-example.html | 19 +++++ .../expansion-overview-example.ts | 8 ++ .../expansion-steps-example.css | 12 +++ .../expansion-steps-example.html | 70 ++++++++++++++++ .../expansion-steps-example.ts | 22 ++++++ tools/tslint-rules/noUnscapedHtmlTagRule.js | 64 +++++++++++++++ tslint.json | 1 + 10 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 src/lib/expansion/expansion.md create mode 100644 src/material-examples/expansion-overview/expansion-overview-example.css create mode 100644 src/material-examples/expansion-overview/expansion-overview-example.html create mode 100644 src/material-examples/expansion-overview/expansion-overview-example.ts create mode 100644 src/material-examples/expansion-steps/expansion-steps-example.css create mode 100644 src/material-examples/expansion-steps/expansion-steps-example.html create mode 100644 src/material-examples/expansion-steps/expansion-steps-example.ts create mode 100644 tools/tslint-rules/noUnscapedHtmlTagRule.js diff --git a/src/lib/expansion/expansion.md b/src/lib/expansion/expansion.md new file mode 100644 index 000000000000..a6c31ac14680 --- /dev/null +++ b/src/lib/expansion/expansion.md @@ -0,0 +1,79 @@ +Angular Material expansion provides a way to show and hide lightweight content, by collapsing and expanding a view with a nice animation. The `expanded` input allows to choose among the collapsed or expanded state. + +Each expansion has a header and an action sections. The header section is always visible at the top of the component and contains a title and a description subsections. The action section is fixed at the bottom, being visible when the expansion is in expanded state + +When grouped by an `` element, the expansions can be used for the creation of flows, as it brings up the possibility to expand one view at a time. + + + +### Events + +The `closed` and `opened` output events are emitted when the expansion is collapsed/expanded. + +### Headers section + +By default, the expansion header has a toogle sign at the right edge, pointing up when the expansion is expanded and down when it's collapsed. The toogle icon can be hiden setting the `toogleHide` to `true`. + +The `` subsecion is shown in the begining of the header, followed by the `` subsection, which is supposed to have a sumary of what's in the expansion content. + +```html + + + This is the expansion title + + + + + + + This the expansion content + + +``` + +For more complex headers, use the `` and `` header selectors: + +```html + + + + This is the expansion title + + + This is a summary of the content + + + +

...

+ +
+``` + +### Accordion + +It's possible to group expansions in a fancy way. The `multi="true"` input allows the expansions state to be set independently of each other. When `multi="false"` (default) just one expansion can be expanded at a given time: + +```html + + + + + This is the expansion 1 title + + + This the expansion 1 content + + + + + + This is the expansion 2 title + + + This the expansion 2 content + + + + +``` + diff --git a/src/lib/icon/icon-registry.ts b/src/lib/icon/icon-registry.ts index 9c590e874936..c7bfd120a1ca 100644 --- a/src/lib/icon/icon-registry.ts +++ b/src/lib/icon/icon-registry.ts @@ -180,7 +180,7 @@ export class MdIconRegistry { } /** - * Returns an Observable that produces the icon (as an DOM element) from the given URL. + * Returns an Observable that produces the icon (as an `` DOM element) from the given URL. * The response from the URL may be cached so this will not always cause an HTTP request, but * the produced element will always be a new copy of the originally fetched icon. (That is, * it will not contain any modifications made to elements previously returned). @@ -207,7 +207,7 @@ export class MdIconRegistry { } /** - * Returns an Observable that produces the icon (as an DOM element) with the given name + * Returns an Observable that produces the icon (as an `` DOM element) with the given name * and namespace. The icon must have been previously registered with addIcon or addIconSet; * if not, the Observable will throw an error. * diff --git a/src/material-examples/expansion-overview/expansion-overview-example.css b/src/material-examples/expansion-overview/expansion-overview-example.css new file mode 100644 index 000000000000..a3c296437609 --- /dev/null +++ b/src/material-examples/expansion-overview/expansion-overview-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ \ No newline at end of file diff --git a/src/material-examples/expansion-overview/expansion-overview-example.html b/src/material-examples/expansion-overview/expansion-overview-example.html new file mode 100644 index 000000000000..ccde7f2b3842 --- /dev/null +++ b/src/material-examples/expansion-overview/expansion-overview-example.html @@ -0,0 +1,19 @@ + + + + Personal data + + + Type your name and age + + + + + + + + + + \ No newline at end of file diff --git a/src/material-examples/expansion-overview/expansion-overview-example.ts b/src/material-examples/expansion-overview/expansion-overview-example.ts new file mode 100644 index 000000000000..e47663d02d86 --- /dev/null +++ b/src/material-examples/expansion-overview/expansion-overview-example.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + + +@Component({ + selector: 'expansion-overview-example', + templateUrl: 'expansion-overview-example.html', +}) +export class ExpansionOverviewExample {} diff --git a/src/material-examples/expansion-steps/expansion-steps-example.css b/src/material-examples/expansion-steps/expansion-steps-example.css new file mode 100644 index 000000000000..36562487f0a4 --- /dev/null +++ b/src/material-examples/expansion-steps/expansion-steps-example.css @@ -0,0 +1,12 @@ +.headers-align .mat-expansion-panel-header-title, +.headers-align .mat-expansion-panel-header-description { + flex-basis: 0; +} + +.icons-to-right { + display: inline-block; + width: 100%; + text-align: right; + margin-top: 5px; + color: blue; +} diff --git a/src/material-examples/expansion-steps/expansion-steps-example.html b/src/material-examples/expansion-steps/expansion-steps-example.html new file mode 100644 index 000000000000..157cc2580511 --- /dev/null +++ b/src/material-examples/expansion-steps/expansion-steps-example.html @@ -0,0 +1,70 @@ + + + + + Personal data + + +
Type your name and age
+
account_circle
+
+ + + + + + + + + + + + + + + + + + + Destination + + +
Type the country name
+
map
+
+
+ + + + + + + + + +
+ + + + + Day of the trip + + +
Inform the date you wish to travel
+
date_range
+
+
+ + + + + + + + + + +
+ +
diff --git a/src/material-examples/expansion-steps/expansion-steps-example.ts b/src/material-examples/expansion-steps/expansion-steps-example.ts new file mode 100644 index 000000000000..137f94065013 --- /dev/null +++ b/src/material-examples/expansion-steps/expansion-steps-example.ts @@ -0,0 +1,22 @@ +import {Component} from '@angular/core'; + + +@Component({ + selector: 'expansion-overview-example', + templateUrl: 'expansion-overview-example.html', +}) +export class ExpansionStepsExample { + public step = 0; + + openEvent(stepNumb: number) { + this.step = stepNumb; + } + + nextStep() { + this.step++; + } + + prevStep() { + this.step--; + } +} diff --git a/tools/tslint-rules/noUnscapedHtmlTagRule.js b/tools/tslint-rules/noUnscapedHtmlTagRule.js new file mode 100644 index 000000000000..e3e0c079abce --- /dev/null +++ b/tools/tslint-rules/noUnscapedHtmlTagRule.js @@ -0,0 +1,64 @@ +const ts = require('typescript'); +const utils = require('tsutils'); +const Lint = require('tslint'); + +const ERROR_MESSAGE = + 'A HTML tag may only appear if it is escaped. ' + + 'This is meant to prevent failures in docs generation caused by a misinterpreted tag.'; + +/** + * Rule that walks through all comments inside of the library and adds failures when it + * detects unescaped HTML tags inside of multi-line comments. + */ +class Rule extends Lint.Rules.AbstractRule { + + apply(sourceFile) { + return this.applyWithWalker(new NoUnescapedHtmlTagWalker(sourceFile, this.getOptions())); + } +} + +class NoUnescapedHtmlTagWalker extends Lint.RuleWalker { + + visitSourceFile(sourceFile) { + utils.forEachComment(sourceFile, (fullText, commentRange) => { + + let isEscapedHtmlTag = true; + while (true) { + const iOpenTag = fullText.indexOf('<'); + const iCloseTag = fullText.indexOf('>'); + if ((iOpenTag === -1) && (iCloseTag === -1)) { + break; + } + if ((iCloseTag < iOpenTag) || (iCloseTag === -1)) { + isEscapedHtmlTag = false; + break; + } + let iTestTag = fullText.indexOf('<', iOpenTag + 1); + if ((iTestTag > iOpenTag) && (iTestTag < iCloseTag)) { + isEscapedHtmlTag = false; + break; + } + iTestTag = fullText.indexOf('`<'); + if (iTestTag !== (iOpenTag - 1)) { + isEscapedHtmlTag = false; + break; + } + iTestTag = fullText.indexOf('>`') + if (iTestTag !== iCloseTag) { + isEscapedHtmlTag = false; + break; + } + if ((iCloseTag + 2) > fullText.length) { + break; + } + fullText = fullText.substring(iCloseTag + 2, fullText.length) + } + + if (commentRange.kind === ts.SyntaxKind.MultiLineCommentTrivia && !isEscapedHtmlTag) { + this.addFailureAt(commentRange.pos, commentRange.end - commentRange.pos, ERROR_MESSAGE); + } + }); + } +} + +exports.Rule = Rule; \ No newline at end of file diff --git a/tslint.json b/tslint.json index 2c9ee2c55180..58cc66ce0ef1 100644 --- a/tslint.json +++ b/tslint.json @@ -28,6 +28,7 @@ "no-unused-expression": true, "no-var-keyword": true, "no-exposed-todo": true, + "no-unescaped-html-tag": true, "no-debugger": true, "no-unused-variable": [true, {"ignore-pattern": "^_"}], "no-rxjs-patch-imports": [