qss 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a8e93da5bd3a65eb8804f5416a1a0315f23110bb6027703c71974b7fa4443d73
4
+ data.tar.gz: d00e38e05740739f64aff39d17f491558f76a0556ec71abaa7781c278059c60c
5
+ SHA512:
6
+ metadata.gz: dc74ce934ef4007d538d184b46822b89bbb3e6ee1c0a2ff90900ae69729434e5413dac0380c33976ae2ba43cf01a9a30e6b67140f4055fdadf758781b31f7be1
7
+ data.tar.gz: aa18e0742c0dfc5bb26067fed5dff96f52b28f0e495634b9aac87e1ead4ed60ae5124cae80b12f5b4fce43f44f2a06f7d8f71f2f7c8e99f0c68b3147f4799931
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to the qss gem. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
4
+ versions follow [Semantic Versioning](https://semver.org/) (before 1.0, minor versions may break the API).
5
+
6
+ ## [0.1.0] - unreleased
7
+
8
+ First release, extracted from the Parapet project.
9
+
10
+ ### Added
11
+ - Core stylesheet (`qss/qss_core.scss`, compiled `qss/qss_core.css`): utilities on a 1000-unit canvas grid; the unit
12
+ (`--qnt`, canvas width / 1000) computed by CSS alone (`0.1cqw` of the canvas; the viewport width outside one).
13
+ - Base reset for QSS actors at the canvas id's weight only, so every core utility applies without the JS engine.
14
+ - Neutral `!default` SCSS settings (`qss/_qss_defaults.scss`); a project sets its own before importing core.
15
+ - Optional runtime engine (`qss/qss-engine.js`): rules for uncovered bracket classes, measured element edges.
16
+ - `QSS::QssNativeAuditor`: id grammar (`{qualifier}-{baseObject}`, `QSSObject` custom types) with a per-project
17
+ registry, `qss-function` / `qss-relation` attributes, explicit dimensions for every actor, unit rules (no raw CSS
18
+ lengths on QSS structure; rem or % only in foreign content), `!important`, z-index and inline-style checks.
19
+ - `QSS::QssAuditor`: the older class-whitelist auditor.
20
+ - `QSS.configure(root:, config:)`: a project's settings read at runtime; paths resolve against its root.
21
+ - `QSS::Blueprints` (`QSS.grid`, `QSS.object`): layout arithmetic and object blueprints.
22
+ - `QSS::Engine`: Rails engine for the asset pipeline, loaded only when Rails is present.
23
+ - `qss-sync`: writes a project's SCSS settings (`--core` regenerates the gem's own generated sections).
24
+ - `qss-core-render-check`: renders the compiled CSS alone in headless Chrome and checks core utilities.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,26 @@
1
+ # Contributing to QSS
2
+
3
+ Thank you for helping. Issues and pull requests live at https://bitbucket.org/kmf2/qss.
4
+
5
+ ## Reporting a bug
6
+
7
+ Please include the QSS version, Ruby (and Rails) version, the smallest markup that shows the problem, and what the
8
+ auditor or browser did versus what you expected.
9
+
10
+ ## Changing code
11
+
12
+ 1. `bundle install`
13
+ 2. Make the change, with a spec for it under `spec/`.
14
+ 3. Run `bundle exec rake` (RuboCop, then the render check) and `bundle exec rspec`; all must pass.
15
+ 4. If you changed `config/grammar.yml`, run `bundle exec rake sync` and commit the regenerated sections. Never edit
16
+ between the `QSS-GENERATED-BEGIN` / `QSS-GENERATED-END` markers by hand.
17
+ 5. If you changed `app/assets/stylesheets/qss/qss_core.scss`, run `bundle exec rake compile` and commit
18
+ `qss_core.css`.
19
+ 6. Add a line to the Unreleased section of `CHANGELOG.md`.
20
+
21
+ QSS keeps layout readable from source: a change that makes a layout depend on rendering, on JavaScript, or on a
22
+ second coordinate system needs a strong reason, stated in the pull request.
23
+
24
+ ## License
25
+
26
+ By contributing, you agree that your contributions are licensed under the MIT License.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright Kraig Fairhurst
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/QSS-MANIFESTO.md ADDED
@@ -0,0 +1,61 @@
1
+ # QSS: Quantized Spatial Styling Manifesto
2
+ ## Version 1.2 — "Semantic Object Architecture"
3
+
4
+ ### 1. The Core Philosophy
5
+ QSS is NOT a CSS framework. It is a **Spatial Operating System** for the browser.
6
+
7
+ Traditional CSS treats the web as a "Document Stream" where elements flow like ink on paper. This is inherently non-deterministic and difficult for AI Agents to reason about without querying the computed DOM.
8
+
9
+ **QSS rejects flow.** It treats the screen as a 1000-unit 2D CAD canvas. Every element has a mathematical origin and a predictable footprint.
10
+
11
+ ### 2. The Deterministic Stack
12
+ To ensure isolation and predictable rendering, QSS requires the **Safety Trio**:
13
+
14
+ 1. **Stage (`#qss-canvas`)**: The relative-positioned root. All spatial math is relative to this origin.
15
+ 2. **Wrapper (`#qss-wrapper`)**: Enforces viewport boundaries and provides a "Safety Gutter."
16
+ 3. **Noun (`id="..."`)**: The unique Identity. Every "Object" on the canvas is a Noun defined by its ID.
17
+ 4. **Actor (`.qss`)**: The mandatory base class (The DNA). It enforces `position: absolute` and a "Nuclear Reset."
18
+
19
+ ### 3. Grammar: The "Adjective" System
20
+ Adjectives define the traits, positioning, and state of a Noun.
21
+
22
+ 1. **Atomic Adjectives** (Classes): `.[prop]\[[val]]` pattern (e.g., `.qss-pos-x[500]`).
23
+ 2. **Parametric Adjectives** (Composite Classes): `.[NounType]\[[p1]|[p2]|...]` pattern.
24
+
25
+ ### 4. Semantic Object Registry & Blueprints
26
+ Version 1.2 introduces **Parametric Blueprints**. While the `id` is the Noun (Identity), the blueprint class (e.g., `.qss-Button`) is a **Composite Adjective** that applies a pre-defined set of traits from `qss-objects.json`.
27
+
28
+ - **Intrinsic Defaults**: Using `.qss-Button` applies the `intrinsic` dimensions defined in the registry.
29
+ - **Parametric Overrides**: Using `.qss-Button[200|80]` overrides specific dimensions (Width | Height) JIT.
30
+
31
+ #### Example: Parametric Dropdown Blueprint
32
+ ```json
33
+ {
34
+ "name": "Dropdown",
35
+ "params": ["w", "h", "row_height"],
36
+ "intrinsic": { "w": 200, "h": 40 },
37
+ "slots": [
38
+ { "name": "header", "pos": [0, 0] },
39
+ { "name": "list", "pos": [0, 42], "h": "computed" }
40
+ ]
41
+ }
42
+ ```
43
+
44
+ ### 5. Deterministic Helpers (Ruby/JS)
45
+ QSS provides a **Grid Generator** that allows Agents to "stamp" complex layouts without visual checks.
46
+
47
+ ```ruby
48
+ # Ruby instantiation
49
+ <% qss.grid(31, cols: 7, w: 100, h: 100).each do |day| %>
50
+ <div class="qss qss-pos-x[<%= day.x %>] qss-pos-y[<%= day.y %>]">...</div>
51
+ <% end %>
52
+ ```
53
+
54
+ ### 6. Installation
55
+ 1. Copy `qss_core.scss` and `_qss_variables.scss` to your stylesheets.
56
+ 2. Include `qss-engine.js` for client-side transpilation.
57
+ 3. Configure `qss.config.json` with your project palette.
58
+ 4. (Optional) Copy `qss.rb` to your `lib/` for server-side spatial math.
59
+
60
+ ---
61
+ *Mathematically Audited. Agent Aware. Deterministic by Design.*
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # QSS: Quantized Spatial Styling
2
+
3
+ QSS is a CSS layout framework built so that both people and AI agents can read a layout from its source, without
4
+ rendering it. Layout is placed and sized on a 1000-unit grid across a **canvas** element: one **qnt** is one
5
+ thousandth of the canvas width, computed by CSS alone. QSS ships compiled CSS, its SCSS sources, an optional
6
+ JavaScript engine, and two **auditors** that check views against QSS's rules. It includes a Rails engine for the
7
+ asset pipeline; the auditors and configuration also work in plain Ruby.
8
+
9
+ > **Status: 0.1.0, early.** QSS was extracted from the Parapet project (a Rails development tool),
10
+ > which is its first consumer. Expect names and APIs to change before 1.0. See [CHANGELOG.md](CHANGELOG.md).
11
+ > Why QSS is designed this way: [docs/DESIGN_HISTORY.md](docs/DESIGN_HISTORY.md).
12
+
13
+ ## Vocabulary
14
+
15
+ - **Canvas**: the element QSS measures against, `<div id="qss-canvas">` by default.
16
+ - **Actor**: an element with class `qss` inside the canvas. Actors declare their size; QSS's reset keeps them from
17
+ shrinking or growing implicitly.
18
+ - **qnt**: the QSS unit, `canvas width / 1000`. `w[240]` means 240 qnt wide: 24% of the canvas, at any screen size.
19
+ - **Noun, adjective, attribute**: an element's `id` is its noun (its identity), its classes are adjectives (its
20
+ traits), and `qss-function` / `qss-relation` are QSS attributes. See [QSS-MANIFESTO.md](QSS-MANIFESTO.md).
21
+ - **Foreign content**: anything inside class `foreign` (or `qss-payload-override`) is left to ordinary CSS.
22
+
23
+ ## Installation (Rails)
24
+
25
+ ```ruby
26
+ # Gemfile
27
+ gem "qss"
28
+ ```
29
+
30
+ The gem's Rails engine puts QSS's assets on your asset pipeline (`qss/qss_core.css`, `qss/qss_core.scss`,
31
+ `qss/qss-engine.js`).
32
+
33
+ ### Markup
34
+
35
+ An id is `{qualifier}-{baseObject}`: the base object is an HTML tag, the qualifier says which one. A qualifier is
36
+ declared once in your registry, recording what it adds to its base. Structural frames (`nav`, `main`, ...) carry
37
+ `contain-layout`.
38
+
39
+ ```erb
40
+ <div id="qss-canvas">
41
+ <nav id="main-nav" class="qss anchored contain-layout w[200] h-full"> ... </nav>
42
+ <section id="content-section" class="qss anchored contain-layout w[800] h-full"> ... </section>
43
+ </div>
44
+ ```
45
+
46
+ ```yaml
47
+ # config/qss_registry.yml (auditor.registry_path in your config, below)
48
+ types:
49
+ main-nav:
50
+ extends: nav
51
+ content-section:
52
+ extends: section
53
+ ```
54
+
55
+ This example audits green with `QSS::QssNativeAuditor` (below).
56
+
57
+ ### Stylesheet: neutral defaults
58
+
59
+ ```erb
60
+ <%= stylesheet_link_tag "qss/qss_core" %>
61
+ ```
62
+
63
+ ### Stylesheet: with your own settings
64
+
65
+ Set your values first, then import core; core's settings are `!default`, so yours win. Put
66
+ `QSS.stylesheets_path` on your Sass load path so `qss/qss_core` resolves:
67
+
68
+ ```scss
69
+ // app/assets/stylesheets/application.scss
70
+ @import "qss_variables"; // generated from your config by qss-sync (below)
71
+ @import "qss/qss_core";
72
+ ```
73
+
74
+ ```ruby
75
+ Sass.compile("app/assets/stylesheets/application.scss",
76
+ load_paths: ["app/assets/stylesheets", QSS.stylesheets_path])
77
+ ```
78
+
79
+ ### The JavaScript engine (optional)
80
+
81
+ The compiled CSS works on its own. The engine adds rules at runtime for bracket classes the compiled CSS does not
82
+ cover, and exports measured element edges as CSS variables:
83
+
84
+ ```erb
85
+ <%= javascript_include_tag "qss/qss-engine", defer: true %>
86
+ <script>
87
+ document.addEventListener("DOMContentLoaded", () => { QSSEngine.startPulse(); QSSEngine.startObserver(); });
88
+ </script>
89
+ ```
90
+
91
+ ## Configuration
92
+
93
+ QSS starts neutral. A project declares its own settings in one YAML file and tells QSS where it is:
94
+
95
+ ```ruby
96
+ # config/initializers/qss.rb
97
+ QSS.configure(root: Rails.root, config: "config/qss_config.yml")
98
+ ```
99
+
100
+ ```yaml
101
+ # config/qss_config.yml -- every key is optional; see the gem's config/grammar.yml for the defaults
102
+ config:
103
+ portal_root: "#overlay-root" # overlays render here; "" = rules scoped to the canvas only
104
+ palette:
105
+ brand-main: "#0f1115"
106
+ group_names: [menu] # named groups for group-*:hover style classes
107
+ auditor:
108
+ id_prefix: "app-" # optional project id prefix
109
+ registry_path: "config/qss_registry.yml"
110
+ sync_targets:
111
+ variables: app/assets/stylesheets/_qss_variables.scss
112
+ ```
113
+
114
+ Relative paths resolve against the declared `root`, never the working directory.
115
+
116
+ ### Generating your SCSS settings
117
+
118
+ ```sh
119
+ QSS_CONSUMER_CONFIG=config/qss_config.yml bundle exec qss-sync
120
+ ```
121
+
122
+ This writes your `_qss_variables.scss` (the `sync_targets.variables` path). Without `QSS_CONSUMER_CONFIG` it reads
123
+ `config/qss_config.yml` from the current directory.
124
+
125
+ ## Auditing views
126
+
127
+ ```ruby
128
+ result = QSS::QssNativeAuditor.audit_file("app/views/layouts/application.html.erb")
129
+ result[:status] # => "green", "orange" or "red"
130
+ result[:issues] # => [{ type:, message:, severity: }, ...] (plus code: on most identity and unit findings)
131
+ ```
132
+
133
+ RED means a rule is violated: fix the markup, or reconsider the rule. ORANGE is a judgment call. Examples of rules:
134
+ every actor declares its width and height (or opts out with `qss-content-driven`); structure carries no raw CSS
135
+ lengths (sizes are in qnt or canvas percentages); no `!important`; ids follow the `{qualifier}-{baseObject}`
136
+ grammar. `QSS::QssAuditor` is the older class-whitelist auditor: it predates the bracket vocabulary (it reports
137
+ `w[200]` as unknown) and is kept for projects that still use its whitelist.
138
+
139
+ ## Requirements
140
+
141
+ - Ruby 3.2 or newer. Rails is optional (needed only for the asset-pipeline engine).
142
+ - A current browser with CSS container query units (`cqw`), `@property` and `:where()`.
143
+
144
+ ## Development
145
+
146
+ ```sh
147
+ bundle install
148
+ bundle exec rspec # the test suite (plain Ruby)
149
+ bundle exec rake rubocop # lint
150
+ bundle exec rake compile # rebuild app/assets/stylesheets/qss/qss_core.css
151
+ bundle exec rake sync # regenerate the generated sections from config/grammar.yml
152
+ bundle exec rake render_check # render qss_core.css alone in headless Chrome (needs selenium-webdriver)
153
+ ```
154
+
155
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
156
+
157
+ ## License
158
+
159
+ MIT. See [MIT-LICENSE](MIT-LICENSE).