Permalink
Browse files

chore(git): Merge branch 'import-export'.

  • Loading branch information...
chriseppstein committed Nov 29, 2018
2 parents f1259df + 8481fa3 commit 595feabf4b11884423f481ca9c9ac2537bf5761a
Showing with 1,734 additions and 982 deletions.
  1. +25 −25 OLD_README.md
  2. +13 −13 README.md
  3. +6 −6 packages/@css-blocks/core/README.md
  4. +2 −1 packages/@css-blocks/core/src/Analyzer/ElementAnalysis.ts
  5. +13 −16 packages/@css-blocks/core/src/BlockCompiler/ConflictResolver.ts
  6. +2 −2 packages/@css-blocks/core/src/BlockCompiler/index.ts
  7. +5 −2 packages/@css-blocks/core/src/BlockParser/BlockParser.ts
  8. +101 −0 packages/@css-blocks/core/src/BlockParser/features/export-blocks.ts
  9. +119 −0 packages/@css-blocks/core/src/BlockParser/features/import-blocks.ts
  10. +0 −70 packages/@css-blocks/core/src/BlockParser/features/resolve-references.ts
  11. +102 −0 packages/@css-blocks/core/src/BlockParser/utils/blockNamesParser.ts
  12. +19 −9 packages/@css-blocks/core/src/BlockSyntax/BlockSyntax.ts
  13. +1 −1 packages/@css-blocks/core/src/BlockSyntax/parseBlockDebug.ts
  14. +48 −3 packages/@css-blocks/core/src/BlockTree/Block.ts
  15. +4 −4 packages/@css-blocks/core/src/BlockTree/RulesetContainer.ts
  16. +1 −1 packages/@css-blocks/core/src/importing/types.ts
  17. +229 −0 packages/@css-blocks/core/test/BlockParser/block-construction-test.ts
  18. +102 −0 packages/@css-blocks/core/test/BlockParser/block-name-test.ts
  19. +536 −0 packages/@css-blocks/core/test/BlockParser/import-export-test.ts
  20. +47 −0 packages/@css-blocks/core/test/BlockParser/native-at-rules-test.ts
  21. +43 −0 packages/@css-blocks/core/test/BlockParser/native-pseudos-test.ts
  22. +205 −0 packages/@css-blocks/core/test/BlockParser/selector-validation-test.ts
  23. +1 −1 packages/@css-blocks/core/test/attribute-container-test.ts
  24. +2 −2 packages/@css-blocks/core/test/block-factory-test.ts
  25. +8 −8 packages/@css-blocks/core/test/block-inheritance-test.ts
  26. +3 −3 packages/@css-blocks/core/test/block-interface-test.ts
  27. +4 −4 packages/@css-blocks/core/test/global-states-test.ts
  28. +2 −2 packages/@css-blocks/core/test/local-scope-test.ts
  29. +23 −23 packages/@css-blocks/core/test/resolution-test.ts
  30. +0 −718 packages/@css-blocks/core/test/syntax-test.ts
  31. +8 −8 packages/@css-blocks/core/test/template-analysis-test.ts
  32. +2 −2 packages/@css-blocks/core/test/validations/attribute-parent-validator-test.ts
  33. +41 −41 packages/@css-blocks/core/test/validations/property-conflict-validator-test.ts
  34. +1 −1 packages/@css-blocks/core/test/validations/root-class-validator-test.ts
  35. +1 −1 packages/@css-blocks/ember-cli/README.md
  36. +1 −1 packages/@css-blocks/ember-cli/tests/dummy/lib/in-repo-addon/package.json
  37. +1 −1 packages/@css-blocks/ember-cli/tests/dummy/lib/in-repo-engine/package.json
  38. +1 −1 packages/@css-blocks/ember-cli/tests/dummy/lib/in-repo-lazy-engine/package.json
  39. +2 −2 packages/@css-blocks/glimmer/README.md
  40. +1 −1 packages/@css-blocks/glimmer/test/fixtures/readme-app/src/ui/components/page-layout/stylesheet.css
  41. +2 −2 ...css-blocks/glimmer/test/fixtures/styled-app/src/ui/components/with-dynamic-classes/stylesheet.css
  42. +1 −1 ...@css-blocks/glimmer/test/fixtures/styled-app/src/ui/components/with-dynamic-states/stylesheet.css
  43. +1 −1 ...css-blocks/glimmer/test/fixtures/styled-app/src/ui/components/with-multiple-blocks/stylesheet.css
  44. +4 −4 packages/@css-blocks/jsx/test/analyzer/class-states-objstr-test.ts
  45. +1 −1 packages/@css-blocks/webpack/test/fixtures/blocks/has-reference.block.css
@@ -373,7 +373,7 @@ Root specific declarations:
the file's path is not a legal CSS identifier. Note: the way a path becomes
a name is configurable on a per-application or framework integration basis.
* `implements`: a space separated list of block names that have already been
declared with `@block-reference` (See below).
declared with `@block` (See below).
* `extends`: the value is name of a single block from which to inherit the
styles and public interface. Note that this does not change the output of
the block but instead it affects the classes that are used in the templates
@@ -425,16 +425,16 @@ E.g. `.button[state|size=large], .button[state|size=small]`.
### Block References
You can declare a dependency on another block with the `@block-reference`
You can declare a dependency on another block with the `@block`
@-rule. Block references don't cause any styles to be included. Instead,
they are like an ES6 `import` statement -- they make it possible to refer to
the public interface of another block from within the current block and to
resolve any namespace collisions with locally preferred identifiers.
A `@block-reference` creates a locally scoped alias for the styles in the referenced block:
A `@block` creates a locally scoped alias for the styles in the referenced block:
```css
@block-reference icons from "../../shared/styles/icons/dark.block.css";
@block icons from "../../shared/styles/icons/dark.block.css";
```
### Conflicting Block Names
@@ -457,7 +457,7 @@ automatically generate a unique name for BEM output mode.
`my-component/styles.block.css`
```css
@block-reference shared from "../shared.block.css";
@block shared from "../shared.block.css";
:scope {
block-name: my-block;
@@ -510,7 +510,7 @@ elements.
`navigation.block.css`
```css
@block-reference app from "application.block.css";
@block app from "application.block.css";
app[state|is-saving] .signout,
.signout[state|disabled] {
@@ -530,7 +530,7 @@ block object.
- `:scope` represents the block root for the current block.
- `a-block-reference.root` represents the block root for the
block that has a `@block-reference` as `a-block-reference` from the current
block that has a `@block` as `a-block-reference` from the current
block. In many cases, the `:scope` can be safely omitted.
- `[state|foo]` or `[state|foo=bar]` represent the
root state named `foo` or the state named `foo` with the substate of `bar`.
@@ -617,7 +617,7 @@ Rather than having to specify the block root, a block class can declare itself t
```
// tabs.block.css
@block-reference tab from "tab.block.css";
@block tab from "tab.block.css";
:scope {
display: flex;
}
@@ -674,7 +674,7 @@ To inherit from another block you must first define a reference to the
other block:
```css
@block-reference another from "./another-block.block.css";
@block another from "./another-block.block.css";
```
And now that block can be referenced within this file by the name
@@ -712,8 +712,8 @@ implementation of that interface. To accomplish this, you can declare
a block `implements` one or more blocks.
```css
@block-reference base from "./base.block.css";
@block-reference other from "./other.block.css";
@block base from "./base.block.css";
@block other from "./other.block.css";
:scope { implements: base, other; color: red; }
```
@@ -768,7 +768,7 @@ that conflict in another block object's selectors.
```css
/* header.block.css */
@block-reference other from "./other.css";
@block other from "./other.css";
.header {
border: none;
border: resolve("other.nav");
@@ -822,7 +822,7 @@ local values to take precedence.
```css
/* header.block.css */
@block-reference other from "./other.css";
@block other from "./other.css";
.header {
border: resolve("other.nav");
border: none;
@@ -854,7 +854,7 @@ selectors of that same pseudo-element are resolved.
```css
/* lists.block.css */
@block-reference links from "./links.block.css";
@block links from "./links.block.css";
.list-item::before {
content: "*";
content: resolve("links.external");
@@ -893,7 +893,7 @@ Example:
```css
/* lists.block.css */
@block-reference links from "./links.block.css";
@block links from "./links.block.css";
.list-item {
color: purple;
color: resolve("links.external");
@@ -967,8 +967,8 @@ same local identifier for the block with the global state. Example:
```css
/* icons.block.css */
@block-reference article from "./article.block.css";
@block-reference app from "./app.block.css";
@block article from "./article.block.css";
@block app from "./app.block.css";
.icon {
color: white;
color: resolve("app[state|is-loading] article.link");
@@ -1026,7 +1026,7 @@ Example:
```css
/* icons.block.css */
@block-reference article from "./article.block.css";
@block article from "./article.block.css";
.icon {
color: white;
color: resolve-all("article.link");
@@ -1119,7 +1119,7 @@ local values to take precedence.
```css
/* header.block.css */
@block-reference other from "./other.css";
@block other from "./other.css";
.header {
font-size: 16px;
font-size: 1rem;
@@ -1173,7 +1173,7 @@ Consider the following conflicts when `target.main` and `conflicts.article` are
```css
/* conflicts.block.css */
@block-reference target from "./target.css";
@block target from "./target.css";
[state|happy] .article {
color: green;
color: resolve("target.main");
@@ -1217,7 +1217,7 @@ Specifically for any property that has a conflict with the super block element
of the same value in the key selector the following resolution is created:
```css
@block-reference base from "./base.block.css";
@block base from "./base.block.css";
:scope { extends: base; }
.foo {
color: resolve("base.foo");
@@ -1235,8 +1235,8 @@ composition of the necessary styles as it's own class.
File: `navigation.block.scss`
```scss
@block-reference super-grid-system from "super-grid-system.block.css";
@block-reference drop-down from "drop-down.block.css";
@block super-grid-system from "super-grid-system.block.css";
@block drop-down from "drop-down.block.css";
.profile {
float: --unset;
@@ -1269,7 +1269,7 @@ You must also tell the debug statement where to output the information.
Example:
```css
@block-reference icons from "../../shared/styles/icons/dark.block.css";
@block icons from "../../shared/styles/icons/dark.block.css";
@block-debug icons to comment;
```
@@ -1423,7 +1423,7 @@ the current component's styles:
`my-component/styles.block.css`
```css
@block-reference icons from "../../shared/styles/icons/dark.block.css";
@block icons from "../../shared/styles/icons/dark.block.css";
:scope {
border: 1px solid black;
@@ -111,7 +111,7 @@ CSS Blocks is under active development and there are a number of features that h
| ❌ | <code>[state&#124;name=value]</code> | Bare state (not associated with an Originating Element) and optional substate selectors for targeting all elements in the Block that possess the state an/or sub-state. |
| 🖌 | <code>.class[state&#124;name default]</code> | Default state value to be applied when there is no other match. |
| **At Rules** ||
| ✅ | `@block-reference local-name from "./file/path.css"` | Reference another Block using a local name. |
| ✅ | `@block local-name from "./file/path.css"` | Reference another Block using a local name. |
| ✅ | `@block-debug block-name to channel` | Debug call that will print a block interface to a "channel": `comment`, `stderr`, or `stdout`. |
| ✅ | `@block-global block.path` | Declare a Block class or state as public. It may be used as a context selector in other Blocks. |
| 🖌 | `@is-block block-name` | Block class can declare itself to be the root of another block in a specific state or set of states. |
@@ -296,14 +296,14 @@ There are only two (2) common-sense rules to follow when using Block styles in y
# 🏗 Block Composition
Blocks styles are, by design, scoped to the file they are written in, but we all know that in a real app your styles can't live in a vacuum!
As you'll see below, there are many methods to compose blocks together in your application. However, most of these methods will begin with the humble `@block-reference`.
As you'll see below, there are many methods to compose blocks together in your application. However, most of these methods will begin with the humble `@block`.
## Block References
A Block may declare a dependency on another Block by using a `@block-reference` at the top of your file. A `@block-reference` creates a locally scoped alias where you can access the public API (declared classes and states) of the referenced block.
A Block may declare a dependency on another Block by using a `@block` at the top of your file. A `@block` creates a locally scoped alias where you can access the public API (declared classes and states) of the referenced block.
Block references don't cause any styles to be included. Instead, they are like an ES6 `import` statement -- they make it possible to refer to the public interface of another Block from within the current Block.
Adding a `@block-reference` is as simple as this:
Adding a `@block` is as simple as this:
```css
/* block-1.block.css */
@@ -314,14 +314,14 @@ Adding a `@block-reference` is as simple as this:
```css
/* block-2.block.css */
@block-reference other-block from "./block-1.block.css";
@block other-block from "./block-1.block.css";
:scope { block-name: block-2; }
```
> 🔮 **Future Feature: Node Modules Block Resolution**
>
> Whether you're integrating with a 3rd party library, or pulling in dependencies internal to your company, at some point you'll want to integrate with styles delivered via NPM! The resolution logic for `@block-reference`s to `node_modules` hasn't yet been implemented yet, but you can track progress (or even help out!) [over on Github](https://github.com/linkedin/css-blocks/issues/112).
> Whether you're integrating with a 3rd party library, or pulling in dependencies internal to your company, at some point you'll want to integrate with styles delivered via NPM! The resolution logic for `@block`s to `node_modules` hasn't yet been implemented yet, but you can track progress (or even help out!) [over on Github](https://github.com/linkedin/css-blocks/issues/112).
With the above code, `block-2` now has a local reference `other-block` which points to `block-1`. We can now freely use the `other-block` identifier inside of `block-2` when we want to reference reference `block-1`. This comes in handy! Especially with features like:
@@ -341,7 +341,7 @@ You do this via the special `implements` property in a Block's `:scope` selector
```css
/* block-2.block.css */
@block-reference other-block from "./block-1.block.css";
@block other-block from "./block-1.block.css";
:scope {
block-name: block-2;
@@ -363,7 +363,7 @@ For the build to pass, we need to implement the *full public interface* of `bloc
```css
/* block-2.block.css */
@block-reference other-block from "./block-1.block.css";
@block other-block from "./block-1.block.css";
:scope {
block-name: block-2;
@@ -403,7 +403,7 @@ Instead, we can simply extend the `<basic-form>` Block, and only apply the small
```css
/* danger-form.block.css */
@block-reference basic-form from "./basic-form.block.css";
@block basic-form from "./basic-form.block.css";
:scope { extends: basic-form; }
.button { background-color: darkred; }
@@ -465,7 +465,7 @@ Block Paths take the form:
block.class[state|name='value']
```
All sections of this selector – except the leading Block name – are optional. The leading Block name *must* refer to an imported `@block-reference` at the top of the file. If css-blocks is unable to resolve a Block Path at build time, you will get a friendly error message in your console!
All sections of this selector – except the leading Block name – are optional. The leading Block name *must* refer to an imported `@block` at the top of the file. If css-blocks is unable to resolve a Block Path at build time, you will get a friendly error message in your console!
All the following syntaxes are legal to select any given stylable on a referenced Block:
@@ -509,7 +509,7 @@ For Glimmer, using multiple blocks in a single template will look something like
```css
/* stylesheet.css */
@block-reference other from "./hoverable.css";
@block other from "./hoverable.css";
:scope { block-name: main; }
.form {
@@ -679,7 +679,7 @@ So, for the following two Blocks where `my-class-1[state|enabled]` and `my-class
```css
/* main.css */
@block-reference other from "./other.css";
@block other from "./other.css";
.my-class-2::before {
border-width: 2px;
@@ -724,7 +724,7 @@ This is most useful for global application states – like during initial applic
```css
/* navigation.block.css */
@block-reference app from "application.block.css";
@block app from "application.block.css";
/* Gray out signout button when app is saving */
app[state|is-saving] .signout {
@@ -12,7 +12,7 @@
| **rootDir** | `process.cwd()` | The root directory from which all sources are relative. |
| **outputMode** | `"BEM"` | Block file output mode. One of [OutputMode][OUTPUT_MODE] |
| **preprocessors** | `{}` | A preprocessor function can be declared by [Syntax][SYNTAX]. |
| **importer** | [`FilesystemImporter`](./src/importing/FilesystemImporter.ts) | A custom importer to resolve identifiers passed to `@block-reference`. |
| **importer** | [`FilesystemImporter`](./src/importing/FilesystemImporter.ts) | A custom importer to resolve identifiers passed to `@block`. |
| **importerData** | `{}` | Additional data to make available to the importer. |
| **maxConcurrentCompiles** | `4` | Limits block parsing and compilation to this number of threads at any one time. |
| **disablePreprocessChaining** | `false` | If a preprocessor function is declared for `css`, all blocks will be ran through it, even those that were pre-processed for another syntax. This can be disabled by setting `disablePreprocessChaining` to true. |
@@ -39,7 +39,7 @@ Container Nodes...contain other nodes ;) These nodes contain logical groupings o
#### Block
A `Block` node is always the root of any `BlockTree`. A `Block` may be parent to any number of `BlockClass`es. The `:scope` selector is considered a special kind of `BlockClass` selector and is also stored as a child of `Block`.
`Block` nodes also store all data related to any `@block-reference`s, the `block-name`, implemented `Blocks`, the inherited `Block`, and any other metadata stored in the Block file. `Block`s also have a special `rootClass` property that points directly to the child `BlockClass` that represents the parsed `:scope` selector .
`Block` nodes also store all data related to any `@block`s, the `block-name`, implemented `Blocks`, the inherited `Block`, and any other metadata stored in the Block file. `Block`s also have a special `rootClass` property that points directly to the child `BlockClass` that represents the parsed `:scope` selector .
#### Attribute
An `Attribute` node represents a single unique attribute `namespace|name` pair and is a parent to any number of `AttrValue` nodes, which represent all the possible attribute values for this `Attribute` discovered in the Block file. An `Attribute` node's parent is always a `BlockClass`. Attribute selectors where no value is specified are considered a special kind of `AttrValue` and is also stored as a child of `Attribute`.
@@ -80,7 +80,7 @@ Block compilation becomes a little more complicated once we begin emitting confl
:scope[state|active] .bar { color: blue; }
/* main.css */
@block-reference other from "./other.css";
@block other from "./other.css";
:scope { block-name: "main"; }
:scope:hover .foo { color: red; color: resolve("other.bar"); }
```
@@ -196,9 +196,9 @@ The **configuration** package contains the CSS Blocks build configuration utilit
See the options table at the top of this file for configuration object details.
## /src/importing
CSS Blocks needs to know where to get a Block file's contents when provided a file `FileIdentifier` from an `@block-reference`. Most of the time, this file path will be a file on disk, in which case the default importer delivered with CSS Blocks will work out of the box. However, in cases where custom resolution of `@block-reference`s are required, consumers are able to provide their own implementation of the CSS Blocks `Importer` interface to deliver this custom behavior.
CSS Blocks needs to know where to get a Block file's contents when provided a file `FileIdentifier` from an `@block`. Most of the time, this file path will be a file on disk, in which case the default importer delivered with CSS Blocks will work out of the box. However, in cases where custom resolution of `@block`s are required, consumers are able to provide their own implementation of the CSS Blocks `Importer` interface to deliver this custom behavior.
A custom importer may be passed to CSS Blocks via the `importer` options of the configuration object. Custom importers will understand how to resolve information about the `FileIdentifier` passed to `@block-reference` and are used to abstract application or platform specific path resolution logic.
A custom importer may be passed to CSS Blocks via the `importer` options of the configuration object. Custom importers will understand how to resolve information about the `FileIdentifier` passed to `@block` and are used to abstract application or platform specific path resolution logic.
Any CSS Blocks `Importer` **must** implement the interface defined for a CSS Blocks `Importer` in [`/src/importing/types.ts`](./src/importing/types.ts). Every importer is required to have a number of introspection methods that return standard metadata for a given `FileIdentifier`:
@@ -214,7 +214,7 @@ For any custom importers that require extra data to be passed by the end-user, t
CSS Blocks ships with two (2) pre-defined importers.
1. `FilesystemImporter`: This is the default importer used by CSS Blocks if no other is provided. It enables `@block-reference`s to resolve relative and absolute file references
1. `FilesystemImporter`: This is the default importer used by CSS Blocks if no other is provided. It enables `@block`s to resolve relative and absolute file references
2. `PathAliasImporter`: The PathAliasImporter is a replacement for the fileystem importer. Relative import paths are first checked to see if they match an existing file relative to the from identifier (when provided). Then if the relative import path has a first segment that is any of the aliases provided the path will be made absolute using that alias's path location. Finally any relative path is resolved against the `rootDir` specified in the CSS Block configuration options.
## /src/util
@@ -793,7 +793,8 @@ function mapChoiceClasses(
configuration: ResolvedConfiguration,
map: Map<string, Style>,
includeAbsent: boolean,
...styles: Style[],
// tslint:disable-next-line:multiline-parameters trailing-comma // ignored due to bug in lint rule
...styles: Style[]
): AttributeValueChoice {
let choices = new Array<AttributeValueChoiceOption>();
if (includeAbsent) {
Oops, something went wrong.

0 comments on commit 595feab

Please sign in to comment.