diff --git a/addon/components/bread-crumb.js b/addon/components/bread-crumb.js index 8282c25..387a671 100644 --- a/addon/components/bread-crumb.js +++ b/addon/components/bread-crumb.js @@ -2,8 +2,10 @@ import Ember from 'ember'; import layout from '../templates/components/bread-crumb'; const { - Component, - computed + get, + set, + computed, + Component } = Ember; const { oneWay, @@ -14,8 +16,28 @@ export default Component.extend({ layout, tagName: 'li', classNameBindings: ['crumbClass'], + attributeBindings: [], crumbClass: oneWay('breadCrumbs.crumbClass'), linkClass: oneWay('breadCrumbs.linkClass'), - hasBlock: bool('template').readOnly() + hasSchema: oneWay('breadCrumbs.hasSchema'), + hasBlock: bool('template').readOnly(), + itemscope: true, + itemtype: 'http://schema.org/ListItem', + itemprop: 'itemListElement', + + position: computed('index', function() { + return Number(this.get('index') + 1); + }).readOnly(), + + init() { + this._super(...arguments); + const hasSchema = get(this, 'breadCrumbs.hasSchema'); + + if (hasSchema) { + const newAttributeBindings = ['itemprop', 'itemscope', 'itemtype']; + + set(this, 'attributeBindings', this.attributeBindings.concat(newAttributeBindings)); + } + } }); diff --git a/addon/components/bread-crumbs.js b/addon/components/bread-crumbs.js index d17cdab..a1740a6 100644 --- a/addon/components/bread-crumbs.js +++ b/addon/components/bread-crumbs.js @@ -3,6 +3,7 @@ import layout from '../templates/components/bread-crumbs'; const { get, + set, Component, computed, copy, @@ -13,6 +14,7 @@ const { typeOf, setProperties, getOwner, + LinkComponent, A: emberArray, String: { classify } } = Ember; @@ -26,11 +28,29 @@ export default Component.extend({ tagName: 'ol', linkable: true, reverse: false, + hasSchema: false, classNameBindings: ['breadCrumbClass'], + attributeBindings: [], + itemscope: true, + itemtype: 'http://schema.org/BreadcrumbList', hasBlock: bool('template').readOnly(), currentUrl: readOnly('applicationRoute.router.url'), currentRouteName: readOnly('applicationRoute.controller.currentRouteName'), + init() { + this._super(...arguments); + + LinkComponent.reopen({ + attributeBindings: ['itemscope', 'itemtype', 'itemprop'] + }); + + if (get(this, 'hasSchema')) { + const newAttributeBindings = ['itemscope', 'itemtype']; + + set(this, 'attributeBindings', this.attributeBindings.concat(newAttributeBindings)); + } + }, + routeHierarchy: computed('currentUrl', 'currentRouteName', 'reverse', { get() { const currentRouteName = getWithDefault(this, 'currentRouteName', false); diff --git a/addon/templates/components/bread-crumb.hbs b/addon/templates/components/bread-crumb.hbs index 195e94a..fd49634 100644 --- a/addon/templates/components/bread-crumb.hbs +++ b/addon/templates/components/bread-crumb.hbs @@ -1,15 +1,31 @@ {{#if route.linkable}} - {{#link-to route.path class=linkClass}} - {{#if hasBlock}} - {{yield this route}} - {{else}} - {{route.title}} - {{/if}} + {{#link-to route.path class=linkClass itemscope=true itemtype="http://schema.org/Thing" itemprop="item"}} + {{#if hasBlock}} + {{yield this route}} + {{else}} + {{#if hasSchema}} + + {{route.title}} + + {{else}} + {{route.title}} + {{/if}} + {{/if}} {{/link-to}} + {{#if hasSchema}} + + {{/if}} {{else}} {{#if hasBlock}} {{yield this route}} {{else}} - {{route.title}} + {{#if hasSchema}} + + {{route.title}} + + + {{else}} + {{route.title}} + {{/if}} {{/if}} {{/if}} diff --git a/addon/templates/components/bread-crumbs.hbs b/addon/templates/components/bread-crumbs.hbs index 96520f6..c54944f 100644 --- a/addon/templates/components/bread-crumbs.hbs +++ b/addon/templates/components/bread-crumbs.hbs @@ -1,7 +1,7 @@ -{{#each routeHierarchy as |route|}} +{{#each routeHierarchy as |route index|}} {{#if hasBlock}} {{yield this route}} {{else}} - {{bread-crumb route=route breadCrumbs=this}} + {{bread-crumb route=route breadCrumbs=this index=index}} {{/if}} {{/each}} diff --git a/tests/acceptance/integration-test.js b/tests/acceptance/integration-test.js index 5e5e274..bc5c22c 100644 --- a/tests/acceptance/integration-test.js +++ b/tests/acceptance/integration-test.js @@ -297,3 +297,23 @@ test('uses path from breadCrumb if present', function(assert) { assert.equal(currentRouteName(), 'foo.index', 'correct current route name'); }); }); + +test('use schema.org BreadcrumbList Schema if present', function(assert) { + assert.expect(12); + visit('/bar/baz'); + + andThen(() => { + assert.equal(find('#hasSchema').attr('itemtype'), 'http://schema.org/BreadcrumbList', 'correct itemtype'); + assert.equal(find('#hasSchema').attr('itemscope'), '', 'has itemscope'); + assert.equal(find('#hasSchema li:first').attr('itemtype'), 'http://schema.org/ListItem', 'li has itemtype'); + assert.equal(find('#hasSchema li:first').attr('itemscope'), '', 'li has itemscope'); + assert.equal(find('#hasSchema li:first').attr('itemprop'), 'itemListElement', 'li has correct itemprop'); + assert.equal(find('#hasSchema li:first a').attr('itemtype'), 'http://schema.org/Thing', 'li a has correct itemtype'); + assert.equal(find('#hasSchema li:first a').attr('itemprop'), 'item', 'li a has correct itemprop'); + assert.equal(find('#hasSchema li:first a').attr('itemscope'), '', 'li a has correct itemscope'); + assert.equal(find('#hasSchema li:first a span').attr('itemprop'), 'name', 'li a span has correct itemprop'); + assert.equal(find('#hasSchema li:first > meta').attr('itemprop'), 'position', 'meta tag itemprop should be position'); + assert.equal(find('#hasSchema li:first > meta').attr('content'), '1', '1st meta tag correct content'); + assert.equal(find('#hasSchema li:last > meta').attr('content'), '2', '2nd meta tag correct content'); + }); +}); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 24aa40d..afe3320 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -14,6 +14,10 @@ {{bread-crumbs id="foundationNotLinkable" tagName="ul" outputStyle="foundation" linkable=false}}
+

With BreadcrumbList Schema

+{{bread-crumbs id="hasSchema" hasSchema=true}} +
+

Custom block

{{#bread-crumbs id="customBlock" as |component route|}} {{#bread-crumb route=route breadCrumbs=component}}