npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@css-blocks/glimmer

v1.5.0

Published

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

Downloads

339

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.