feat(aio): set “avoid” class by convention (filename has “.avoid.”)

Most important for StyleGuide which lost example css class in migration.
Also hides copy for “avoid” files.
This commit is contained in:
Ward Bell 2017-05-02 22:39:14 -07:00 committed by Matias Niemelä
parent 673d8ae583
commit 9ca2b4c967
5 changed files with 58 additions and 42 deletions

View File

@ -12,7 +12,7 @@
}
</code-pane>
<code-pane title='HTML content file' language='html'>&lt;h1&gt;Heading&lt;/h1&gt;</code-pane>
<code-pane title='JSON data file' language='json' class='is-anti-pattern'>{ "key": "value" }</code-pane>
<code-pane title='JSON data file' language='json' class='avoid'>{ "key": "value" }</code-pane>
</code-tabs>
<p></p>
@ -24,7 +24,7 @@
}
</code-pane>
<code-pane title='HTML content file' language='html'>&lt;h1&gt;Heading&lt;/h1&gt;</code-pane>
<code-pane title='JSON data file' language='json' class='is-anti-pattern'>{ "key": "value" }</code-pane>
<code-pane title='JSON data file' language='json' class='avoid'>{ "key": "value" }</code-pane>
</code-tabs>
<p></p>
@ -36,7 +36,7 @@
}
</code-pane>
<code-pane title='HTML content file' language='html' linenums='true'>&lt;h1&gt;Heading&lt;/h1&gt;</code-pane>
<code-pane title='JSON data file' language='json' class='is-anti-pattern'>{ "key": "value" }</code-pane>
<code-pane title='JSON data file' language='json' class='avoid'>{ "key": "value" }</code-pane>
</code-tabs>
<p></p>
@ -76,7 +76,7 @@
</code-example>
<p>An "avoid" header on this one.</p>
<code-example class="is-anti-pattern" title="hero-details.component.ts (Avoid)">
<code-example class="avoid" title="hero-details.component.ts (Avoid)">
&lt;hero-details <em>nghost-pmm-5&gt;
&lt;h2 </em>ngcontent-pmm-5&gt;Mister Fantastic&lt;/h2&gt;
&lt;hero-team <em>ngcontent-pmm-5 </em>nghost-pmm-6&gt;

View File

@ -1,5 +1,5 @@
/* tslint:disable component-selector */
import { Component, ElementRef, OnInit } from '@angular/core';
import { Component, ElementRef, HostBinding, OnInit } from '@angular/core';
import { getBoolFromAttribute } from 'app/shared/attribute-utils';
/**
@ -17,12 +17,13 @@ import { getBoolFromAttribute } from 'app/shared/attribute-utils';
selector: 'code-example',
template: `
<header *ngIf="title">{{title}}</header>
<aio-code [ngClass]="{'headed-code':title, 'simple-code':!title}" [code]="code"
<aio-code [ngClass]="classes" [code]="code"
[language]="language" [linenums]="linenums" [path]="path" [region]="region" [hideCopy]="hideCopy"></aio-code>
`
})
export class CodeExampleComponent implements OnInit {
classes: {};
code: string;
language: string;
linenums: boolean | number;
@ -31,6 +32,9 @@ export class CodeExampleComponent implements OnInit {
title: string;
hideCopy: boolean;
@HostBinding('class.avoidFile')
isAvoid = false;
constructor(private elementRef: ElementRef) {
const element = this.elementRef.nativeElement;
@ -39,7 +43,14 @@ export class CodeExampleComponent implements OnInit {
this.path = element.getAttribute('path') || '';
this.region = element.getAttribute('region') || '';
this.title = element.getAttribute('title') || '';
this.hideCopy = getBoolFromAttribute(element, ['hidecopy', 'hide-copy']);
this.isAvoid = this.path.indexOf('.avoid.') !== -1;
this.hideCopy = this.isAvoid || getBoolFromAttribute(element, ['hidecopy', 'hide-copy']);
this.classes = {
'headed-code': !!this.title,
'simple-code': !this.title,
};
}
ngOnInit() {

View File

@ -11,7 +11,7 @@ describe('Attribute Utilities', () => {
testEl = div.querySelector('div');
});
describe('#getAttrs', () => {
describe('getAttrs', () => {
beforeEach(() => {
this.expectedMap = {
@ -34,7 +34,7 @@ describe('Attribute Utilities', () => {
});
});
describe('#getAttrValue', () => {
describe('getAttrValue', () => {
let attrMap: { [index: string]: string };
beforeEach(() => {
@ -46,7 +46,7 @@ describe('Attribute Utilities', () => {
});
it('should return empty string value for attribute "A"', () => {
expect(getAttrValue(attrMap, 'a')).toBe('');
expect(getAttrValue(attrMap, 'A')).toBe('');
});
it('should return "true" for attribute "b"', () => {
@ -54,11 +54,10 @@ describe('Attribute Utilities', () => {
});
it('should return empty string value for attribute "d-E"', () => {
expect(getAttrValue(attrMap, 'd-e')).toBe('');
expect(getAttrValue(attrMap, 'd-E')).toBe('');
});
it('should return empty string for attribute ["d-e"]', () => {
// because d-e will be found before d
expect(getAttrValue(attrMap, ['d-e'])).toBe('');
});
@ -82,48 +81,48 @@ describe('Attribute Utilities', () => {
});
describe('#boolFromValue', () => {
let attrMap: { [index: string]: string };
describe('boolFromValue', () => {
beforeEach(() => {
attrMap = getAttrs(testEl);
it('should return true for "" as in present but unassigned attr "a"', () => {
expect(boolFromValue('')).toBe(true);
});
it('should return true for present but unassigned attr "a"', () => {
expect(boolFromValue(getAttrValue(attrMap, 'a'))).toBe(true);
it('should return false for "false" as in attr "c"', () => {
expect(boolFromValue('false')).toBe(false);
});
it('should return true for "true" as in attr "b"', () => {
expect(boolFromValue('true')).toBe(true);
});
it('should return true for attr "b" which is "true"', () => {
expect(boolFromValue(getAttrValue(attrMap, 'b'))).toBe(true);
it('should return true for something other than "false"', () => {
expect(boolFromValue('foo')).toBe(true);
});
it('should return false for attr "c" which is "false"', () => {
expect(boolFromValue(getAttrValue(attrMap, 'c'))).toBe(false);
it('should return true for "False" because case-sensitive', () => {
expect(boolFromValue('False')).toBe(true);
});
it('should return false by default for undefined attr "x"', () => {
expect(boolFromValue(getAttrValue(attrMap, 'x'))).toBe(false);
it('should return false by default as in undefined attr "x"', () => {
expect(boolFromValue(undefined)).toBe(false);
});
it('should return true for undefined attr "x" when default is true', () => {
const value = getAttrValue(attrMap, 'x');
expect(boolFromValue(value, true)).toBe(true);
it('should return true for undefined value when default is true', () => {
expect(boolFromValue(undefined, true)).toBe(true);
});
it('should return false for undefined attr "x" when default is false', () => {
const value = getAttrValue(attrMap, 'x');
expect(boolFromValue(value, false)).toBe(false);
it('should return false for undefined value when default is false', () => {
expect(boolFromValue(undefined, false)).toBe(false);
});
it('should return true for present but unassigned attr "a" even when default is false', () => {
it('should return true for "" as in unassigned attr "a" even when default is false', () => {
// default value is only applied when the attribute is missing
const value = getAttrValue(attrMap, 'a');
expect(boolFromValue(value, false)).toBe(true);
expect(boolFromValue('', false)).toBe(true);
});
});
// Combines the three utilities for convenience.
describe('#getBoolFromAttribute', () => {
describe('getBoolFromAttribute', () => {
it('should return true for present but unassigned attr "a"', () => {
expect(getBoolFromAttribute(testEl, 'a')).toBe(true);
});

View File

@ -17,16 +17,19 @@ export function getAttrs(el: HTMLElement | ElementRef): StringMap {
}
/**
* Return the attribute that matches `atty`.
* @param atty Name of the attribute or a string of candidate attribute names
* Return the attribute that matches `attr`.
* @param attr Name of the attribute or a string of candidate attribute names
*/
export function getAttrValue(attrs: StringMap, attr: string | string[] = ''): string {
return attrs[typeof attr === 'string' ? attr : attr.find(a => attrs[a] !== undefined)];
return attrs[typeof attr === 'string' ?
attr.toLowerCase() :
attr.find(a => attrs[a.toLowerCase()] !== undefined)
];
}
/**
* Return the boolean state of an attribute value (if supplied)
* @param attyValue The string value of some attribute (or undefined if attribute not present)
* @param attrValue The string value of some attribute (or undefined if attribute not present)
* @param def Default boolean value when attribute is undefined.
*/
export function boolFromValue(attrValue: string, def: boolean = false) {

View File

@ -28,13 +28,16 @@ code-example header {
margin: -17px;
}
code-example.is-anti-pattern header {
code-example.avoid header,
code-example.avoidFile header {
border: 2px solid $anti-pattern;
background: $anti-pattern;
}
code-example.is-anti-pattern,
code-tabs.is-anti-pattern md-tab-body {
code-example.avoid,
code-example.avoidFile,
code-tabs.avoid md-tab-body,
code-tabs.avoidFile md-tab-body {
border: 0.5px solid $anti-pattern;
}