Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@css-blocks/glimmer

linkedin64BSD-2-Clause1.5.0TypeScript support: included

Statically analyze & rewrite the css-block styles in Handlebars templates.

glimmer, static, analysis, handlebars, @css-blocks/core, css, optimizer

readme

CSS Blocks Integration for Glimmer Applications

The css-blocks Rewriter and Analyzer for Glimmer templates.

Installation

yarn add @css-blocks/glimmer

or

npm install --save-dev @css-blocks/glimmer

Usage

This integration for css-blocks with Glimmer creates a convention where every component has an associated css-block. The classes and states of that block are exposed by default to the template. Other blocks are exposed to the template using the @block at-rule from within the stylesheet.

Template Syntax

Given the following CSS Block definition:

@block grid from "./grid.block.css";
:scope {
  block-name: my-component;
  /* ... */
}
:scope[loading] { /* ... */ }
.sidebar { /* ... */ }
.sidebar[collapsed] { /* ... */ }
.main { /* ... */ }
.recommended { /* ... */ }
.one-fifth { /* ... */ }
.one-fifth[gutter-right] { /* ... */ }
.four-fifths { /* ... */ }

We can style a glimmer template like so:

<div block:scope block:loading={{isLoading}}>
  <aside block:class="sidebar" grid:class="one-fifth" block:collapsed grid:gutter="right">
  </aside>
  <article class="{{style-if isRecommended 'recommended' 'main'}}" grid:class="four-fifths">
  </article>
</div>

Of note here:

  • Templates with a corresponding Block file must have a root single DOM node as the base of its template.
  • The styles for the :scope class are automatically applied to the root element of the component (in this case: div).
  • Classes and states from referenced blocks are prefixed with the name of the block (in this case: grid)
  • The only expressions allowed in class attributes are the CSS Blocks specific {{style-if}} and {{style-unless}} helpers. Otherwise, a build time error is thrown.

Creating an Analyzer

The default Analyzer performs a transitive analysis by traversing the component hierarchy as well as the block's dependencies on other blocks. This analysis can be provided to the css-blocks compiler and optimizer to remove dead css and enable powerful optimizations.

import * as path from "path";
import {
  Project,
  Rewriter,
  HandlebarsTransitiveStyleAnalyzer as Analyzer
} from "@css-blocks/glimmer";
import projectConfig from "./projectConfig";
let projectDir = path.resolve(__dirname, "..");
let project = new Project(projectDir, projectConfig);
let analyzer = new Analyzer(project, "my-app-component");
analyzer.analyze().then((analysis) => {
  console.log(analysis.serialize(projectDir));
});

Glimmer Project Layout for CSS Blocks

You must add a new stylesheet type to your project so that every component has an associated CSS block. This means you must declare a new type in the types section and add "stylesheet" to the component types.

Example:

const glimmerProjectConfiguration = {
  types: {
    application: { definitiveCollection: 'main' },
    component: { definitiveCollection: 'components' },
    helper: { definitiveCollection: 'components' },
    renderer: { definitiveCollection: 'main' },
    template: { definitiveCollection: 'components' },
    stylesheet: { definitiveCollection: 'components' }
  },
  collections: {
    main: {
      types: ['application', 'renderer']
    },
    components: {
      group: 'ui',
      types: ['component', 'template', 'helper', 'stylesheet'],
      defaultType: 'component',
      privateCollections: ['utils']
    }
  }
}

Note: at this time the default block file for a component must be named stylesheet.css -- the standard naming convention of *.block.css does not work.

Rewriting Templates

After analyzing templates and compiling & optimizing the CSS blocks that are used, the glimmer template must be rewritten to use the right classnames. Glimmer accepts AST plugins during the precompilation step.

Here's an example script for how to analyze and rewrite a single template. Integration with your specific build system will be required.

import * as path from "path";
import {
  StyleMapping
} from "@css-blocks/core";
import {
  Project,
  Rewriter,
  RewriterOptions,
  HandlebarsStyleAnalyzer as Analyzer,
} from "@css-blocks/glimmer";
import {
  precompile
} from "@glimmer/compiler";
import projectConfig from "./projectConfig";
let projectDir = path.resolve(__dirname, "..");
let project = new Project(projectDir, projectConfig);
let analyzer = new Analyzer(project, "my-app-component");
analyzer.analyze().then((analysis) => {
  let template = project.templateFor("my-app-component");
  let options = {
    meta: {},
    plugins: {
      ast: [Rewriter]
    },
    cssBlocks: {
      styleMapping: StyleMapping.fromAnalysis(analysis)
    }
  };
  let compiledFile = precompile(template.string, options);
});

To Do

  • Default the name for a component's main block stylesheet to the name of the component so that :scope { block-name: name-of-component; } is not required.

changelog

Change Log

All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.

1.5.0 (2020-09-16)

Note: Version bump only for package @css-blocks/glimmer

1.4.0 (2020-09-04)

Note: Version bump only for package @css-blocks/glimmer

1.3.2 (2020-08-20)

Note: Version bump only for package @css-blocks/glimmer

1.3.0 (2020-08-11)

Note: Version bump only for package @css-blocks/glimmer

1.2.2 (2020-08-05)

Bug Fixes

1.2.0 (2020-08-05)

Bug Fixes

  • Allow null in typeguards. (f69c457)
  • Analysis serialization had incorrect source locations. (9969614)
  • Only add an analysis for block:scope if it's not explicitly there. (8ee7d51)

Features

  • Deserializing block definition files & analysis in the ember-app. (ec338bf)
  • Infrastructure for single pass analyzer & rewriter. (466b933)

1.1.2 (2020-07-20)

Bug Fixes

  • Linter error. (dfcb62e)
  • Switches in the rewrite didn't work with inheritance. (360a28f)

1.1.1 (2020-06-30)

Note: Version bump only for package @css-blocks/glimmer

1.0.0 (2020-04-04)

Bug Fixes

  • Some packages were erroneously marked as MIT license. (6ba8462)

chore

  • Drop support for node 6, 8, and 11. (3806e82)

Features

  • style-of: Allows positional arguements to be passed. (2eb25a8)
  • style-of: Errors if unsupported params have been passed. (cbee078)

BREAKING CHANGES

  • Node 8 is now out of maintainence so we have dropped support for node 6 and 8. Node 11 is no longer needed because node 12 was released.

1.0.0-alpha.6 (2020-02-19)

Bug Fixes

  • Avoid Promise.all() because of possible race conditions. (61d0e54)
  • Properly parse and rewrite style-of subexpressions. (7c42b2a)
  • There were crashes when running with some debugging enabled. (80dca43)

1.0.0-alpha.5 (2020-02-14)

Features

  • Add style-of helper for glimmer. (afcc846), closes #383

1.0.0-alpha.4 (2019-12-18)

Bug Fixes

  • Dynamic scope attributes were not being analyzed or rewritten. (488e23e), closes #371 #373

1.0.0-alpha.3 (2019-12-11)

Bug Fixes

  • Use the AST builders provided by to the plugin. (f0d6387)

1.0.0-alpha.2 (2019-12-10)

Bug Fixes

  • A block compilation error would cause the template to be skipped. (9f6c57d)
  • Handle missing block files in glimmer apps. (4e984d4)

1.0.0-alpha.1 (2019-12-10)

Bug Fixes

  • Discover new glimmer components when they are added while watching. (f3386ac)
  • Fix dev build performance issue. (bf9bd06), closes #357

1.0.0-alpha.0 (2019-11-22)

Bug Fixes

  • Fix bugs introduced by per-block namespaces. (180b416)
  • Fixing a few lint errors after a rebase. (4a05b40)
  • Fixing tests. (7d368cc)
  • For when the block-alias is the same name as a generated className. (bd36033)
  • Small tweaks around parameter passing. (5d91c56)
  • Using the export syntax for blocks in tests. (bc86451)

Features

  • Introducing the block-alias. (5517d72)
  • Passing all block aliases as reserved classNames for compilation. (aea5fcc)
  • Per block namespaces. (053ed47)
  • Respect explicit exports for a block interface. (d37e704)

0.24.0 (2019-09-16)

Features

  • Invalidate handlebar template caches when dependent blocks change. (e3fd6f2)
  • Track ranges instead of only the start position for errors. (f7f2dfb)

0.23.2 (2019-06-13)

Note: Version bump only for package @css-blocks/glimmer

0.23.0 (2019-05-08)

Note: Version bump only for package @css-blocks/glimmer

0.22.0 (2019-05-02)

Note: Version bump only for package @css-blocks/glimmer

0.21.0 (2019-04-07)

Features

0.20.0 (2019-03-11)

Features

0.20.0-beta.7 (2019-02-01)

Bug Fixes

  • Build AMD glimmer helpers in ES5 for IE11 support. (213aad8)

0.20.0-beta.6 (2019-02-01)

Bug Fixes

  • Build AMD glimmer helpers in ES5 for IE11 support. (213aad8)

0.20.0-beta.5 (2019-01-08)

Bug Fixes

  • Deliver both 'visitor' and 'visitors' for Glimmer AST Plugins. (e7d6fad)

Features

0.20.0-beta.4 (2018-10-19)

Features

  • Manually throw error for Node 6 in Analyzer. (5788fcc)

0.20.0-beta.3 (2018-10-01)

Features

  • Ember CLI addon Preprocessor support. (574483d)

0.20.0-beta.0 (2018-08-20)

Features

  • broccoli: Add naive caching strategy for Broccoli. (#190) (d63626f)
  • ember-cli: Ember cli classic (#185). (865267c)

0.19.0 (2018-04-25)

Note: Version bump only for package @css-blocks/glimmer

0.18.0 (2018-04-24)

Bug Fixes

  • Update global states to use simplified parser utils. (b953602)

Features

  • Enable root-level typedoc generation for the project. (557fd49)
  • Enable root-level typedoc generation for the project. (59c85a3)

0.17.0 (2017-12-08)

Bug Fixes

  • rewriter: glimmer requires that subexpressions be helper invocations. (bae23cb)
  • runtime: the expression must always be read. (06e3667)
  • call seal() on element analyses before using them. (51d7a09)
  • handle inheritance in runtime class expressions. (953b734)
  • Only enforce a value's presence in a dynamic switch condition if the condition is not disabled due to a missing style dependency. (13cbd58)