├── app
├── .gitkeep
├── services
│ └── body-class.js
└── helpers
│ └── set-body-class.js
├── addon
├── .gitkeep
├── helpers
│ └── set-body-class.js
└── services
│ └── body-class.js
├── vendor
└── .gitkeep
├── tests
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ ├── .gitkeep
│ │ │ └── application.js
│ │ ├── templates
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ └── application.hbs
│ │ ├── router.js
│ │ ├── styles
│ │ │ └── app.css
│ │ ├── app.js
│ │ └── index.html
│ ├── public
│ │ ├── robots.txt
│ │ └── crossdomain.xml
│ └── config
│ │ ├── targets.js
│ │ ├── optional-features.json
│ │ └── environment.js
├── test-helper.js
├── fastboot
│ └── set-body-class-test.js
├── acceptance
│ ├── test-bleed-test.js
│ └── index-test.js
└── index.html
├── .watchmanconfig
├── index.js
├── config
├── environment.js
└── ember-try.js
├── .npmignore
├── .prettierrc.js
├── .template-lintrc.js
├── .ember-cli
├── .eslintignore
├── .release-it.js
├── renovate.json
├── .gitignore
├── .editorconfig
├── ember-cli-build.js
├── testem.js
├── .github
└── workflows
│ ├── release.yml
│ └── ci.yml
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── .eslintrc.js
├── package.json
├── RELEASE.md
└── CHANGELOG.md
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/app/services/body-class.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-set-body-class/services/body-class';
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | name: 'ember-set-body-class',
5 | };
6 |
--------------------------------------------------------------------------------
/app/helpers/set-body-class.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-set-body-class/helpers/set-body-class';
2 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (/* environment, appConfig */) {
4 | return {};
5 | };
6 |
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | browsers: ['last 1 Chrome versions', 'last 1 year'],
5 | };
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /config/ember-try.js
2 | /dist
3 | /tests
4 | /tmp
5 | .*
6 | *.tgz
7 | ember-cli-build.js
8 | RELEASE.md
9 | renovate.json
10 | testem.js
11 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | printWidth: 100,
5 | semi: true,
6 | arrowParens: 'avoid',
7 | singleQuote: true,
8 | trailingComma: 'es5',
9 | };
10 |
--------------------------------------------------------------------------------
/.template-lintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | extends: 'octane',
5 | rules: {
6 | 'no-action': 'off',
7 | 'no-curly-component-invocation': 'off',
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/tests/dummy/config/optional-features.json:
--------------------------------------------------------------------------------
1 | {
2 | "application-template-wrapper": false,
3 | "default-async-observers": true,
4 | "jquery-integration": false,
5 | "template-only-glimmer-components": true
6 | }
7 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import Application from 'dummy/app';
2 | import config from 'dummy/config/environment';
3 | import { setApplication } from '@ember/test-helpers';
4 | import { start } from 'ember-qunit';
5 |
6 | setApplication(Application.create(config.APP));
7 | start();
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import EmberRouter from '@ember/routing/router';
2 | import config from './config/environment';
3 |
4 | export default class Router extends EmberRouter {
5 | location = config.locationType;
6 | rootURL = config.rootURL;
7 | }
8 |
9 | Router.map(function () {});
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/application.js:
--------------------------------------------------------------------------------
1 | import Controller from '@ember/controller';
2 |
3 | export default class ApplicationController extends Controller {
4 | redText = true;
5 | blueBackground = false;
6 | textSize = 'small-text';
7 | textSizes = ['small-text', 'medium-text', 'large-text'];
8 | }
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | body.red-text {
2 | color: red;
3 | }
4 |
5 | body.blue-background {
6 | background-color: #6666ff;
7 | }
8 |
9 | body.small-text {
10 | font-size: medium;
11 | }
12 | body.medium-text {
13 | font-size: large;
14 | }
15 | body.large-text {
16 | font-size: xx-large;
17 | }
18 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 | /vendor/
4 |
5 | # compiled output
6 | /dist/
7 | /tmp/
8 |
9 | # dependencies
10 | /bower_components/
11 | /node_modules/
12 |
13 | # misc
14 | /coverage/
15 | !.*
16 |
17 | # ember-try
18 | /.node_modules.ember-try/
19 | /bower.json.ember-try
20 | /package.json.ember-try
21 |
--------------------------------------------------------------------------------
/.release-it.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'release-it-lerna-changelog': {
4 | infile: 'CHANGELOG.md',
5 | },
6 | },
7 | git: {
8 | commitMessage: 'v${version}',
9 | tagAnnotation: 'v${version}',
10 | },
11 | github: {
12 | release: true,
13 | releaseName: 'v${version}',
14 | tokenRef: 'GITHUB_AUTH',
15 | },
16 | npm: {
17 | publish: false,
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:js-lib",
4 | ":automergePatch",
5 | ":dependencyDashboard",
6 | ":maintainLockFilesWeekly",
7 | ":semanticCommitsDisabled"
8 | ],
9 |
10 | "postUpdateOptions": ["yarnDedupeHighest"],
11 |
12 | "packageRules": [
13 | {
14 | "matchCurrentVersion": ">= 1.0.0",
15 | "updateTypes": ["minor"],
16 | "automerge": true
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Application from '@ember/application';
2 | import Resolver from 'ember-resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | export default class App extends Application {
7 | modulePrefix = config.modulePrefix;
8 | podModulePrefix = config.podModulePrefix;
9 | Resolver = Resolver;
10 | }
11 |
12 | loadInitializers(App, config.modulePrefix);
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log*
17 | yarn-error.log
18 | testem.log
19 |
20 | # ember-try
21 | .node_modules.ember-try/
22 | bower.json.ember-try
23 | package.json.ember-try
24 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.hbs]
17 | insert_final_newline = false
18 |
19 | [*.{diff,md}]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/tests/fastboot/set-body-class-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { setup, visit } from 'ember-cli-fastboot-testing/test-support';
3 |
4 | module('Fastboot | set-body-class', function (hooks) {
5 | setup(hooks);
6 |
7 | test('it works', async function (assert) {
8 | let { htmlDocument } = await visit('/');
9 | assert.dom(htmlDocument.body).hasClass('red-text');
10 | assert.dom(htmlDocument.body).hasClass('small-text');
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function (defaults) {
6 | let app = new EmberAddon(defaults, {
7 | // Add options here
8 | });
9 |
10 | /*
11 | This build file specifies the options for the dummy test app of this
12 | addon, located in `/tests/dummy`
13 | This build file does *not* influence how the addon or the app using it
14 | behave. You most likely want to be modifying `./index.js` or app's build file
15 | */
16 |
17 | return app.toTree();
18 | };
19 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | test_page: 'tests/index.html?hidepassed',
5 | disable_watching: true,
6 | launch_in_ci: ['Chrome'],
7 | launch_in_dev: ['Chrome'],
8 | browser_args: {
9 | Chrome: {
10 | mode: 'ci',
11 | args: [
12 | // --no-sandbox is needed when running Chrome inside a container
13 | process.env.TRAVIS ? '--no-sandbox' : null,
14 | '--disable-gpu',
15 | '--headless',
16 | '--remote-debugging-port=9222',
17 | '--window-size=1440,900',
18 | ].filter(Boolean),
19 | },
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/addon/helpers/set-body-class.js:
--------------------------------------------------------------------------------
1 | import Helper from '@ember/component/helper';
2 | import { guidFor } from '@ember/object/internals';
3 | import { inject as service } from '@ember/service';
4 |
5 | export default class SetBodyClassHelper extends Helper {
6 | @service bodyClass;
7 |
8 | id = guidFor(this);
9 |
10 | compute([_classNames]) {
11 | let classNames = _classNames ? _classNames.split(/\s+/) : [];
12 | this.bodyClass.register(this.id, classNames);
13 | }
14 |
15 | willDestroy() {
16 | super.willDestroy(...arguments);
17 | this.bodyClass.deregister(this.id);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 | release:
10 | name: release
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | - uses: actions/setup-node@v2
16 | with:
17 | node-version: 10
18 | registry-url: 'https://registry.npmjs.org'
19 |
20 | - run: yarn install --frozen-lockfile
21 |
22 | - name: auto-dist-tag
23 | run: npx auto-dist-tag@1 --write
24 |
25 | - run: npm publish
26 | env:
27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
28 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/acceptance/test-bleed-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { setupRenderingTest } from 'ember-qunit';
3 | import { render } from '@ember/test-helpers';
4 | import hbs from 'htmlbars-inline-precompile';
5 |
6 | module('Acceptance | CSS class bleeding between tests', function (hooks) {
7 | setupRenderingTest(hooks);
8 |
9 | test('test 1 sets a class', async function (assert) {
10 | assert.dom(document.body).hasNoClass('foo');
11 | await render(hbs`{{set-body-class "foo"}}`);
12 | assert.dom(document.body).hasClass('foo');
13 | });
14 |
15 | test('test 2 ensures that the class is not set anymore', async function (assert) {
16 | assert.dom(document.body).hasNoClass('foo');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How To Contribute
2 |
3 | ## Installation
4 |
5 | * `git clone git@github.com:ef4/ember-set-body-class.git`
6 | * `cd ember-set-body-class`
7 | * `yarn install`
8 |
9 | ## Linting
10 |
11 | * `yarn lint:hbs`
12 | * `yarn lint:js`
13 | * `yarn lint:js --fix`
14 |
15 | ## Running tests
16 |
17 | * `ember test` – Runs the test suite on the current Ember version
18 | * `ember test --server` – Runs the test suite in "watch mode"
19 | * `ember try:each` – Runs the test suite against multiple Ember versions
20 |
21 | ## Running the dummy application
22 |
23 | * `ember serve`
24 | * Visit the dummy application at [http://localhost:4200](http://localhost:4200).
25 |
26 | For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).
27 |
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 | {{content-for "body-footer"}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | {{#if this.redText}}
2 | {{set-body-class "red-text"}}
3 | {{/if}}
4 |
5 | {{#if this.blueBackground}}
6 | {{set-body-class "blue-background"}}
7 | {{/if}}
8 |
9 | {{set-body-class this.textSize}}
10 |
11 |
12 |
13 |
14 |
15 | Text Size:
16 |
21 |
22 |
23 |
24 | Any class name:
25 | {{input value=this.dynamicClassName name="dynamicClassName"}}
26 | {{set-body-class this.dynamicClassName}}
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{content-for "body-footer"}}
31 | {{content-for "test-body-footer"}}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ember-set-body-class
2 | ==============================================================================
3 |
4 | This addon lets you set classes on the body like:
5 |
6 | ```hbs
7 | {{set-body-class "hello"}}
8 | ```
9 |
10 | Whenever the above template is rendered, the `` tag will have class
11 | `hello` added to it. When it's destroyed, the class is removed.
12 |
13 |
14 | Compatibility
15 | ------------------------------------------------------------------------------
16 |
17 | * Ember.js v3.10 or above
18 | * Ember CLI v2.13 or above
19 | * Node.js v10 or above
20 |
21 | This works in both browser and Fastboot. Fastboot support requires at least
22 | Fastboot 1.1.1 (which incorporated the work done in https://github.com/ember-fastboot/fastboot/pull/171).
23 |
24 |
25 | Installation
26 | ------------------------------------------------------------------------------
27 |
28 | ```
29 | ember install ember-set-body-class
30 | ```
31 |
32 |
33 | Contributing
34 | ------------------------------------------------------------------------------
35 |
36 | See the [Contributing](CONTRIBUTING.md) guide for details.
37 |
38 |
39 | License
40 | ------------------------------------------------------------------------------
41 |
42 | This project is licensed under the [MIT License](LICENSE.md).
43 |
--------------------------------------------------------------------------------
/tests/acceptance/index-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { setupApplicationTest } from 'ember-qunit';
3 | import { click, fillIn, visit } from '@ember/test-helpers';
4 |
5 | module('Acceptance | index', function (hooks) {
6 | setupApplicationTest(hooks);
7 |
8 | test('updates body class', async function (assert) {
9 | await visit('/');
10 | assert.dom(document.body).hasClass('red-text').hasClass('unrelated-class');
11 |
12 | // ensure that `{{set-body-class}}` does not render anything to the DOM
13 | let selectBox = this.element.querySelector('[data-test-select]');
14 | let app = selectBox.parentElement;
15 | assert.equal(app.firstElementChild.tagName, 'LABEL');
16 |
17 | await click('input[name=blueBackground]');
18 | assert
19 | .dom(document.body)
20 | .hasClass('red-text')
21 | .hasClass('blue-background')
22 | .hasClass('unrelated-class');
23 |
24 | await click('input[name=redText]');
25 | assert
26 | .dom(document.body)
27 | .doesNotHaveClass('red-text')
28 | .hasClass('blue-background')
29 | .hasClass('unrelated-class');
30 |
31 | await fillIn('input[name=dynamicClassName]', 'blue-background');
32 | await click('input[name=blueBackground]');
33 | assert.dom(document.body).hasClass('blue-background').hasClass('unrelated-class');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (environment) {
4 | let ENV = {
5 | modulePrefix: 'dummy',
6 | environment,
7 | rootURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | },
14 | EXTEND_PROTOTYPES: {
15 | // Prevent Ember Data from overriding Date.parse.
16 | Date: false,
17 | },
18 | },
19 |
20 | APP: {
21 | // Here you can pass flags/options to your application instance
22 | // when it is created
23 | },
24 | };
25 |
26 | if (environment === 'development') {
27 | // ENV.APP.LOG_RESOLVER = true;
28 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
29 | // ENV.APP.LOG_TRANSITIONS = true;
30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
31 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
32 | }
33 |
34 | if (environment === 'test') {
35 | // Testem prefers this...
36 | ENV.locationType = 'none';
37 |
38 | // keep test console output quieter
39 | ENV.APP.LOG_ACTIVE_GENERATION = false;
40 | ENV.APP.LOG_VIEW_LOOKUPS = false;
41 |
42 | ENV.APP.rootElement = '#ember-testing';
43 | ENV.APP.autoboot = false;
44 | }
45 |
46 | if (environment === 'production') {
47 | // here you can enable a production-specific feature
48 | }
49 |
50 | return ENV;
51 | };
52 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | root: true,
5 | parser: 'babel-eslint',
6 | parserOptions: {
7 | ecmaVersion: 2018,
8 | sourceType: 'module',
9 | ecmaFeatures: {
10 | legacyDecorators: true,
11 | },
12 | },
13 | plugins: ['ember'],
14 | extends: ['eslint:recommended', 'plugin:ember/recommended', 'plugin:prettier/recommended'],
15 | env: {
16 | browser: true,
17 | },
18 | rules: {
19 | // these rules disabled for now, but should be fixed eventually
20 | 'ember/no-arrow-function-computed-properties': 'off',
21 | 'ember/no-get': 'off',
22 | 'ember/no-observers': 'off',
23 | },
24 | overrides: [
25 | // test files
26 | {
27 | files: ['tests/**'],
28 | excludedFiles: ['tests/dummy/**'],
29 | rules: {
30 | 'ember/avoid-leaking-state-in-ember-objects': 'off',
31 | },
32 | },
33 |
34 | // node files
35 | {
36 | files: [
37 | '.eslintrc.js',
38 | '.prettierrc.js',
39 | '.release-it.js',
40 | '.template-lintrc.js',
41 | 'ember-cli-build.js',
42 | 'index.js',
43 | 'testem.js',
44 | 'blueprints/*/index.js',
45 | 'config/**/*.js',
46 | 'tests/dummy/config/**/*.js',
47 | ],
48 | excludedFiles: ['addon/**', 'addon-test-support/**', 'app/**', 'tests/dummy/app/**'],
49 | parserOptions: {
50 | sourceType: 'script',
51 | },
52 | env: {
53 | browser: false,
54 | node: true,
55 | },
56 | plugins: ['node'],
57 | extends: ['plugin:node/recommended'],
58 | },
59 | ],
60 | };
61 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - 'v*'
8 | pull_request:
9 |
10 | jobs:
11 | test:
12 | name: Tests
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - uses: volta-cli/action@v1
18 | with:
19 | node-version: 10.x
20 | yarn-version: 1.22.5
21 |
22 | - run: yarn install --frozen-lockfile
23 | - run: yarn lint:js
24 | - run: yarn lint:hbs
25 | - run: yarn ember test
26 |
27 | floating-dependencies:
28 | name: Floating Dependencies
29 | runs-on: ubuntu-latest
30 |
31 | steps:
32 | - uses: actions/checkout@v2
33 | - uses: volta-cli/action@v1
34 | with:
35 | node-version: 10.x
36 | yarn-version: 1.22.5
37 |
38 | - run: yarn install --no-lockfile
39 | - run: yarn ember test
40 |
41 | try-scenarios:
42 | name: "ember-try: ${{ matrix.ember-try-scenario }}"
43 | runs-on: ubuntu-latest
44 | needs: test
45 |
46 | strategy:
47 | fail-fast: true
48 | matrix:
49 | ember-try-scenario:
50 | - ember-3.10
51 | - ember-lts-3.12
52 | - ember-lts-3.16
53 | - ember-lts-3.20
54 | - ember-release
55 | - ember-beta
56 | - ember-canary
57 | - ember-default-with-jquery
58 | - ember-classic
59 |
60 | steps:
61 | - uses: actions/checkout@v2
62 | - uses: volta-cli/action@v1
63 | with:
64 | node-version: 12.x
65 | yarn-version: 1.22.5
66 |
67 | - run: yarn install --frozen-lockfile
68 |
69 | - name: test
70 | run: yarn ember try:one ${{ matrix.ember-try-scenario }} --skip-cleanup
71 |
--------------------------------------------------------------------------------
/addon/services/body-class.js:
--------------------------------------------------------------------------------
1 | import { getOwner } from '@ember/application';
2 | import Service from '@ember/service';
3 | import { A } from '@ember/array';
4 | import { once, cancel } from '@ember/runloop';
5 |
6 | export default class BodyClassService extends Service {
7 | _dom = getOwner(this).lookup('service:-document');
8 | _fastboot = getOwner(this).lookup('service:fastboot');
9 | registrations = new Map();
10 |
11 | register(id, classNames) {
12 | this.registrations.set(id, classNames);
13 | this.scheduleUpdate();
14 | }
15 |
16 | deregister(id) {
17 | this.registrations.delete(id);
18 | this.scheduleUpdate();
19 | }
20 |
21 | get names() {
22 | let allNames = new Set();
23 | for (let classNames of this.registrations.values()) {
24 | for (let className of classNames) {
25 | allNames.add(className);
26 | }
27 | }
28 | return [...allNames];
29 | }
30 |
31 | scheduleUpdate() {
32 | this.scheduledRun = once(this, this.updateBodyClass);
33 | }
34 |
35 | updateBodyClass() {
36 | if (!this._dom) {
37 | return;
38 | }
39 |
40 | let registeredClassNames = this.names;
41 |
42 | let body = this._dom.body;
43 | let attr = body.getAttribute('class');
44 | let classList = A(attr ? attr.split(/\s+/) : []);
45 |
46 | classList.removeObjects(this._previousNames || []);
47 | classList.addObjects(registeredClassNames);
48 |
49 | this._previousNames = registeredClassNames;
50 |
51 | body.setAttribute('class', classList.join(' '));
52 | }
53 |
54 | willDestroy() {
55 | if (this._fastboot && this._fastboot.isFastBoot) {
56 | // prevent FastBoot from removing the CSS classes
57 | // again before the response is sent out
58 | cancel(this.scheduledRun);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-set-body-class",
3 | "version": "1.0.2",
4 | "description": "Fastboot-compatible, template-driven helper for setting classes.",
5 | "keywords": [
6 | "ember-addon",
7 | "body",
8 | "class",
9 | "fastboot"
10 | ],
11 | "license": "MIT",
12 | "author": "Edward Faulkner ",
13 | "directories": {
14 | "doc": "doc",
15 | "test": "tests"
16 | },
17 | "repository": "https://github.com/ef4/ember-set-body-class",
18 | "scripts": {
19 | "build": "ember build",
20 | "lint:hbs": "ember-template-lint .",
21 | "lint:js": "eslint .",
22 | "release": "release-it",
23 | "start": "ember server",
24 | "test": "ember try:each"
25 | },
26 | "dependencies": {
27 | "ember-cli-babel": "^7.22.1"
28 | },
29 | "devDependencies": {
30 | "@ember/optional-features": "2.0.0",
31 | "babel-eslint": "10.1.0",
32 | "ember-cli": "3.27.0",
33 | "ember-cli-dependency-checker": "3.2.0",
34 | "ember-cli-fastboot": "2.2.3",
35 | "ember-cli-fastboot-testing": "0.5.0",
36 | "ember-cli-htmlbars": "5.7.1",
37 | "ember-cli-htmlbars-inline-precompile": "3.0.2",
38 | "ember-cli-inject-live-reload": "2.1.0",
39 | "ember-disable-prototype-extensions": "1.1.3",
40 | "ember-load-initializers": "2.1.2",
41 | "ember-qunit": "4.6.0",
42 | "ember-resolver": "8.0.2",
43 | "ember-sinon": "5.0.0",
44 | "ember-source": "3.27.5",
45 | "ember-source-channel-url": "3.0.0",
46 | "ember-template-lint": "2.21.0",
47 | "ember-try": "1.4.0",
48 | "eslint": "7.29.0",
49 | "eslint-config-prettier": "8.3.0",
50 | "eslint-plugin-ember": "10.5.1",
51 | "eslint-plugin-node": "11.1.0",
52 | "eslint-plugin-prettier": "3.4.0",
53 | "loader.js": "4.7.0",
54 | "prettier": "2.3.2",
55 | "qunit-dom": "1.6.0",
56 | "release-it": "14.10.0",
57 | "release-it-lerna-changelog": "3.1.0"
58 | },
59 | "engines": {
60 | "node": "10.* || 12.* || >= 14.*"
61 | },
62 | "ember-addon": {
63 | "configPath": "tests/dummy/config"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Release
2 |
3 | Releases are mostly automated using
4 | [release-it](https://github.com/release-it/release-it/) and
5 | [lerna-changelog](https://github.com/lerna/lerna-changelog/).
6 |
7 |
8 | ## Preparation
9 |
10 | Since the majority of the actual release process is automated, the primary
11 | remaining task prior to releasing is confirming that all pull requests that
12 | have been merged since the last release have been labeled with the appropriate
13 | `lerna-changelog` labels and the titles have been updated to ensure they
14 | represent something that would make sense to our users. Some great information
15 | on why this is important can be found at
16 | [keepachangelog.com](https://keepachangelog.com/en/1.0.0/), but the overall
17 | guiding principle here is that changelogs are for humans, not machines.
18 |
19 | When reviewing merged PR's the labels to be used are:
20 |
21 | * breaking - Used when the PR is considered a breaking change.
22 | * enhancement - Used when the PR adds a new feature or enhancement.
23 | * bug - Used when the PR fixes a bug included in a previous release.
24 | * documentation - Used when the PR adds or updates documentation.
25 | * internal - Used for internal changes that still require a mention in the
26 | changelog/release notes.
27 |
28 |
29 | ## Release
30 |
31 | Once the prep work is completed, the actual release is straight forward:
32 |
33 | * First, ensure that you have an environment variable with your GitHub token
34 | setup as `GITHUB_AUTH`. This token will be used for generating your changelog
35 | (unauthenticated requests to the GitHub API are heavily throttled) and for
36 | creating the GitHub release. Only "repo" access is needed; no "admin"
37 | or other scopes are required.
38 |
39 | * Next, ensure that you have installed your projects dependencies:
40 |
41 | ```
42 | yarn install
43 | ```
44 |
45 | * And last (but not least 😁) do your release:
46 |
47 | ```
48 | yarn release
49 | ```
50 |
51 | [release-it](https://github.com/release-it/release-it/) manages the actual
52 | release process. It will prompt you to to choose the version number after which
53 | you will have the chance to hand tweak the changelog to be used (for the
54 | `CHANGELOG.md` and GitHub release), then `release-it` continues on to tagging,
55 | pushing the tag and commits, etc. Finally GitHub Actions will build the commit
56 | and push the release to npm.
57 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getChannelURL = require('ember-source-channel-url');
4 |
5 | module.exports = async function () {
6 | return {
7 | useYarn: true,
8 | scenarios: [
9 | {
10 | name: 'ember-3.10',
11 | npm: {
12 | devDependencies: {
13 | 'ember-source': '~3.10.0',
14 | },
15 | },
16 | },
17 | {
18 | name: 'ember-lts-3.12',
19 | npm: {
20 | devDependencies: {
21 | 'ember-source': '~3.12.0',
22 | },
23 | },
24 | },
25 | {
26 | name: 'ember-lts-3.16',
27 | npm: {
28 | devDependencies: {
29 | 'ember-source': '~3.16.0',
30 | },
31 | },
32 | },
33 | {
34 | name: 'ember-lts-3.20',
35 | npm: {
36 | devDependencies: {
37 | 'ember-source': '~3.20.0',
38 | },
39 | },
40 | },
41 | {
42 | name: 'ember-release',
43 | npm: {
44 | devDependencies: {
45 | 'ember-source': await getChannelURL('release'),
46 | },
47 | },
48 | },
49 | {
50 | name: 'ember-beta',
51 | npm: {
52 | devDependencies: {
53 | 'ember-source': await getChannelURL('beta'),
54 | },
55 | },
56 | },
57 | {
58 | name: 'ember-canary',
59 | npm: {
60 | devDependencies: {
61 | 'ember-source': await getChannelURL('canary'),
62 | },
63 | },
64 | },
65 | {
66 | name: 'ember-default-with-jquery',
67 | env: {
68 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
69 | 'jquery-integration': true,
70 | }),
71 | },
72 | npm: {
73 | devDependencies: {
74 | '@ember/jquery': '^1.1.0',
75 | },
76 | },
77 | },
78 | {
79 | name: 'ember-classic',
80 | env: {
81 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
82 | 'application-template-wrapper': true,
83 | 'default-async-observers': false,
84 | 'template-only-glimmer-components': false,
85 | }),
86 | },
87 | npm: {
88 | ember: {
89 | edition: 'classic',
90 | },
91 | },
92 | },
93 | ],
94 | };
95 | };
96 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v1.0.2 (2020-12-02)
2 |
3 | #### :bug: Bug Fix
4 | * [#92](https://github.com/ef4/ember-set-body-class/pull/92) services/body-class: Cancel the scheduled update only on fastboot ([@Turbo87](https://github.com/Turbo87))
5 |
6 | #### :house: Internal
7 | * [#82](https://github.com/ef4/ember-set-body-class/pull/82) Adjust browser targets to transpile optional chaining away ([@Turbo87](https://github.com/Turbo87))
8 |
9 | #### Committers: 1
10 | - Tobias Bieniek ([@Turbo87](https://github.com/Turbo87))
11 |
12 | ## v1.0.1 (2020-10-16)
13 |
14 | #### :memo: Documentation
15 | * [#64](https://github.com/ef4/ember-set-body-class/pull/64) Update README and add basic CONTRIBUTING guide ([@Turbo87](https://github.com/Turbo87))
16 |
17 | #### :house: Internal
18 | * [#70](https://github.com/ef4/ember-set-body-class/pull/70) Convert dummy app objects to native classes ([@Turbo87](https://github.com/Turbo87))
19 | * [#71](https://github.com/ef4/ember-set-body-class/pull/71) template-lint: Fix `no-implicit-this` warnings ([@Turbo87](https://github.com/Turbo87))
20 | * [#68](https://github.com/ef4/ember-set-body-class/pull/68) Add `ember-template-lint` ([@Turbo87](https://github.com/Turbo87))
21 | * [#67](https://github.com/ef4/ember-set-body-class/pull/67) Remove obsolete `eslint-env` directives ([@Turbo87](https://github.com/Turbo87))
22 | * [#65](https://github.com/ef4/ember-set-body-class/pull/65) Add `@ember/optional-features` and CI scenarios without it ([@Turbo87](https://github.com/Turbo87))
23 | * [#63](https://github.com/ef4/ember-set-body-class/pull/63) Update `.npmignore` file ([@Turbo87](https://github.com/Turbo87))
24 |
25 | #### Committers: 1
26 | - Tobias Bieniek ([@Turbo87](https://github.com/Turbo87))
27 |
28 | ## v1.0.0 (2020-10-16)
29 |
30 | #### :boom: Breaking Change
31 | * [#54](https://github.com/ef4/ember-set-body-class/pull/54) Replace `set-body-class` component with helper ([@Turbo87](https://github.com/Turbo87))
32 | * [#55](https://github.com/ef4/ember-set-body-class/pull/55) Drop support for Ember.js v3.8 and v3.9 ([@Turbo87](https://github.com/Turbo87))
33 | * [#24](https://github.com/ef4/ember-set-body-class/pull/24) Drop support for Ember.js v3.7.x and below ([@Turbo87](https://github.com/Turbo87))
34 | * [#13](https://github.com/ef4/ember-set-body-class/pull/13) Drop support for Node v4, v6 and v8 ([@Turbo87](https://github.com/Turbo87))
35 |
36 | #### :rocket: Enhancement
37 | * [#23](https://github.com/ef4/ember-set-body-class/pull/23) Update `ember-cli-babel` to v7.22.1 ([@Turbo87](https://github.com/Turbo87))
38 |
39 | #### :bug: Bug Fix
40 | * [#12](https://github.com/ef4/ember-set-body-class/pull/12) util/get-dom: Fix copy/paste issue in the error message ([@Turbo87](https://github.com/Turbo87))
41 |
42 | #### :memo: Documentation
43 | * [#9](https://github.com/ef4/ember-set-body-class/pull/9) Update Readme with info about Fastboot support ([@acorncom](https://github.com/acorncom))
44 |
45 | #### :house: Internal
46 | * [#61](https://github.com/ef4/ember-set-body-class/pull/61) Add `release-it` to simplify the release process ([@Turbo87](https://github.com/Turbo87))
47 | * [#60](https://github.com/ef4/ember-set-body-class/pull/60) CI: Add `release` job ([@Turbo87](https://github.com/Turbo87))
48 | * [#57](https://github.com/ef4/ember-set-body-class/pull/57) Convert to native classes ([@Turbo87](https://github.com/Turbo87))
49 | * [#26](https://github.com/ef4/ember-set-body-class/pull/26) ember-try: Use `ember-source-channel-url` for release channels ([@Turbo87](https://github.com/Turbo87))
50 | * [#56](https://github.com/ef4/ember-set-body-class/pull/56) CI: Disable broken release channel scenarios ([@Turbo87](https://github.com/Turbo87))
51 | * [#53](https://github.com/ef4/ember-set-body-class/pull/53) Replace unit/integration test with more application tests ([@Turbo87](https://github.com/Turbo87))
52 | * [#52](https://github.com/ef4/ember-set-body-class/pull/52) Remove obsolete `getDOM()` utility ([@Turbo87](https://github.com/Turbo87))
53 | * [#44](https://github.com/ef4/ember-set-body-class/pull/44) renovate: Enable automerging for semver-compatible updates ([@Turbo87](https://github.com/Turbo87))
54 | * [#33](https://github.com/ef4/ember-set-body-class/pull/33) Use `prettier` for code formatting ([@Turbo87](https://github.com/Turbo87))
55 | * [#31](https://github.com/ef4/ember-set-body-class/pull/31) Update ESLint and add Ember and Node plugins ([@Turbo87](https://github.com/Turbo87))
56 | * [#30](https://github.com/ef4/ember-set-body-class/pull/30) tests: Remove unused test-helpers ([@Turbo87](https://github.com/Turbo87))
57 | * [#29](https://github.com/ef4/ember-set-body-class/pull/29) Update `ember-cli-inject-live-reload` to v2.0.2 ([@Turbo87](https://github.com/Turbo87))
58 | * [#28](https://github.com/ef4/ember-set-body-class/pull/28) Use `qunit-dom` for CSS class assertions ([@Turbo87](https://github.com/Turbo87))
59 | * [#27](https://github.com/ef4/ember-set-body-class/pull/27) tests/acceptance: Use `setupApplicationTest()` helper ([@Turbo87](https://github.com/Turbo87))
60 | * [#25](https://github.com/ef4/ember-set-body-class/pull/25) Remove unused/unnecessary dev dependencies ([@Turbo87](https://github.com/Turbo87))
61 | * [#22](https://github.com/ef4/ember-set-body-class/pull/22) Use `ember-cli-fastboot-testing` for fastboot testing ([@Turbo87](https://github.com/Turbo87))
62 | * [#21](https://github.com/ef4/ember-set-body-class/pull/21) Add explicit `ember-try` dev dependency ([@Turbo87](https://github.com/Turbo87))
63 | * [#19](https://github.com/ef4/ember-set-body-class/pull/19) ember-try: Add additional LTS version scenarios ([@Turbo87](https://github.com/Turbo87))
64 | * [#17](https://github.com/ef4/ember-set-body-class/pull/17) Migrate from `ember-cli-qunit` to `ember-qunit` ([@Turbo87](https://github.com/Turbo87))
65 | * [#20](https://github.com/ef4/ember-set-body-class/pull/20) Update fastboot dependencies ([@Turbo87](https://github.com/Turbo87))
66 | * [#16](https://github.com/ef4/ember-set-body-class/pull/16) Add GitHub Actions config ([@Turbo87](https://github.com/Turbo87))
67 | * [#14](https://github.com/ef4/ember-set-body-class/pull/14) Migrate from `ember-cli-eslint` to `eslint` ([@Turbo87](https://github.com/Turbo87))
68 |
69 | #### Committers: 2
70 | - David Baker ([@acorncom](https://github.com/acorncom))
71 | - Tobias Bieniek ([@Turbo87](https://github.com/Turbo87))
72 |
73 |
--------------------------------------------------------------------------------