The [Motivation Page](./motivation.md) has a step-by-step introduction to the CSS features or just play around with the **[JSFiddle of all the steps combined](https://jsfiddle.net/philschatz/hjk2z4af/)**
Book authors need a way to style their book for a PDF and ePUB. Sometimes they need additional elements to properly style. They also need a way to number and move elements around, like solutions in the back of the book.
Rather than letting them write JavaScript and execute arbitrary code, authors can describe both the styling and the movement of elements in the same file.
So, What's the gist of this thing?
When converting HTML there are 3 basic things one needs to do:
lookup attributes or elements (to move)
change (or delete) an element (attributes, tag name)
add new elements
Each of these are accomplished using different parts of CSS:
declaration functions are used to look up information (ie attr(id))
declarations are used to modify an element (ie class-add: "foo", "bar"; or tag-name-set: "h3";)
pseudoelements are used to create new elements (ie ::before { content: "Example"; })
This library aims to address several stories that could be helpful.
Note: ap-physics takes a couple minutes to load and then save
Precise Error Messages
This addresses a few use-cases:
As a CSS Developer I want to know if I mis-typed a rule/function/selector
As a CSS Developer I want to know which CSS and HTML combination caused a crash to occur
As a CSS Developer I want to know when something is unexpectedly empty so I do not have to look for the absence in the baked HTML file
Here are some example error messages from various tests. All but one are already implemented:
test/_errors.css:1:20: WARNING: Skipping unrecognized rule 'contentssss:', maybe a typo? (test/_errors.in.html:8:1)
test/specificity.css:30:28: WARNING: Skippingthis rule because it was overridden by test/specificity.css:42:13 (test/specificity.in.html:8:1)
test/move.css:14:5: WARNING: Moving0 items using selector '.exercise'. You can add a :has() guard to prevent this warning (test/move.in.html:10:1)
test/move.css:14:5: ERROR: Tried to move an HTML element that was already marked for moving. The first move rule was matched by test/move.css:6:3. (test/move.in.html:13:6)
(stack trace here)
test/move.css:7:2: ERROR: Exception occurred while manipulating the DOM (test/move.in.html:13:6)
(stack trace here)
These are formatted in a way that can be parsed by a linter and therefore can show up in your text editor :smile: and they include both the CSS and HTML source location information.
When coupled with source maps (see below), this vastly reduces debugging time because you know exactly where in the CSS file to look and which HTML element was being processed at the time.
Click for Future Work ...
add more errors and warnings
add "Strict" mode that fails on any warnings
create a linter plugin that parses the output text
create an atom plugin that allows you to run from the commandline but report the errors to the atom linter
HTML SourceMaps
This addresses a few use-cases:
As a CSS Developer I want to see why a specific element, class, or piece of generated text is showing up
As a Content Editor I want to review the baked HTML file but when I find a content problem I want to find the source so I can edit it
As a GUI Developer I want people to see what the book looks like (collated & numbered) but when I click to edit I want to edit the original content
As a CSS Developer I want to see what all is being affected by a CSS selector/rule so I know if it is affecting the right elements
Animation
In this animation the left pane contains the baked HTML and the right pane contains the source that generated the code (either HTML content or CSS selectors/rules).
As you click in the left pane, the right pane updates.
(there is no trickery here, this is real working code using the plugin atom-sourcemap)
Click for Future Work ...
The right pane could show the original SCSS instead of the CSS file so you can edit and save directly
In the left pane the HTML could be rendered instead of looking at the HTML Source. Then, when you click around, the right pane would still do the same thing it does now.
This sourcemap information could be loaded into a WYSIWYG editor so an author can view the baked book but edit the source Page/Module (this animation only showed 1 source HTML file and 1 source CSS file)
Sourcemaps could be used to provide more precise validation errors (ie broken links, unused class names)
Exactly 1 Pass
This addresses a few use-cases:
As a CSS Developer I want to not have to reason about intermediate state of the DOM
As a CSS Developer I want the conversion to be fast
This model is inspired by both CSS and virtualdom libraries like React: you describe what you want the result to look like rather than the steps to get to the result.
No more writing the intermediate steps needed to get to the desired result (ie setting temporary attributes, multiple passes to move things around).
Parallelizing
Since each element does not depend on the state of other elements (and there is only 1 pass), the conversion can be parallelized, further reducing the conversion time.
CSS and HTML Coverage
css-plus generates an ${OUTPUT_HTML}.lcov file in addition to the ${OUTPUT_HTML}.map file which contains all the CSS covered and the HTML elements that were matched during the conversion.
This is just a script that takes 2 HTML files (raw and baked HTML) and builds a sourcemap file by looking at the id attributes of elements. It is not precise but may be "good enough" to use in the short term for things like:
Content Editors fixing typos or broken links
WYSIWYG Editor that renders the baked HTML file but edits the raw when you click on something
It is also useful for XSLT passes (like CNXML -> HTML) that have no way to otherwise generate a sourcemap
This shows a full baked textbook in Atom in the left pane and the raw book file in the right pane. It does not open up the CSS file in the right pane because the sourcemap was not generated using css-plus
There are 3 phases (annotate, build a work tree, manipulate):
The entire HTML DOM is annotated with rulesets that match each element
The DOM is traversed (in-order but that does not matter).
Selectors/declarations that require looking at DOM nodes are evaluated at this point and any manipulations that need to happen are added to a work-tree (as Closures/Promises)
elements that will move are marked to see if 2 rules are moving the same element (aka Mark-Sweep in Garbage-Collection terms)
The DOM is manipulated by evaluating the closures in the work-tree
Click for Future Work ...
mark the elements that will be moved
ensure empty elements are not created (no children or attributes have been added)
support a --dry-run which renders the work tree
optionally specify a selector to only show elements you are interested in
Screencasts
Debugging Example:
Example of converting an entire book (takes a few minutes but you get progress bars and status updates):
Running from the commandline
You can install this globally or as a package in an existing project.
To install and run globally, run npm install --global css-plus
Then you can run:
css-plus --css ${INPUT_CSS} --html ${INPUT_HTML} --output ${OUTPUT_HTML}# Or if you are lazy:
css-plus ${INPUT_CSS}${INPUT_HTML}${OUTPUT_HTML}
To install locally and run, type npm install --save css-plus
Then you can run the previous examples but replace css-plus with $(npm bin)/css-plus
Sourcemap Approximator
This takes 2 XML/HTML files (ie raw & baked) and builds a rough sourcemap using the id attribute of elements.
show console warnings/errors in the output HTML area
Support attrs-remove: * instead of attrs-set: because they are as interchangeable and the order-of-evaluation is easier (only need to know 2: attrs-add: and attrs-remove:)
::for-each(1, descendant, ${SELECTOR}):has(${SELECTOR_FOR_MATCHES}) should have an additional selector argument
so it only creates the element if there is something matching the selector
This way a "Homework" section will not be created if there are no Homework problems to show
Show colorful error messages
Show colorful warnings
Support attributes with a namespace (like <div epub:type="glossary"> in EPUB3 epub:type )
Support the original selectivity for vanilla declarations (having padding: 0; padding-top: 1em; is different than padding-top: 1em; padding: 0;)
output CSS should have 1 class for each selector (so sourcemaps will point to the original selector)
warn/error about unused selectors and declarations (useful while developing to make sure you seleected something)
create a debugger: true; declaration so you do not have to edit the HTML file to set a breakpoint
create a content: inject-svg(/path/to/file.svg) maybe? Or an xinclude: declaration so we can inject SVG files withough having to rely on background-image's
create an ::inside-matches(1, '> selector') so we can wrap the body of a note but not the title... actually, we could just move the title so maybe done
add a function that converts a number to upper-al lower-alpha arabic roman, etc
add a count-ancestors-of-type(selector) to determine heading level (h1, h2, h3, ...)
FAQs
The [Motivation Page](./motivation.md) has a step-by-step introduction to the CSS features or just play around with the **[JSFiddle of all the steps combined](https://jsfiddle.net/philschatz/hjk2z4af/)**
We found that css-plus demonstrated a not healthy version release cadence and project activity because the last version was released a year ago.It has 1 open source maintainer collaborating on the project.
Package last updated on 20 Apr 2018
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.