jekyll-theme-modootoday 1.1.0 → 1.1.1
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 +4 -4
- data/CHANGELOG.md +29 -1
- data/README.ko.md +2 -1
- data/README.md +2 -1
- data/RULES.md +7 -2
- data/_includes/modootoday/breadcrumb.html +1 -1
- data/_includes/modootoday/config.html +5 -4
- data/_includes/modootoday/head-meta.html +4 -2
- data/_includes/modootoday/jsonld/breadcrumb.html +1 -1
- data/_includes/modootoday/jsonld/publisher.html +1 -1
- data/_includes/modootoday/jsonld/website.html +1 -1
- data/_includes/modootoday/lang-switch.html +4 -2
- data/_includes/modootoday/link.html +5 -2
- data/_includes/modootoday/markdown/lists.html +26 -0
- data/_includes/modootoday/markdown/sections.html +20 -6
- data/_includes/modootoday/ref-url.html +12 -0
- data/_includes/modootoday/stylesheets.html +1 -0
- data/_layouts/default.html +4 -2
- data/_sass/modootoday/base/_prose.scss +1 -0
- data/_sass/modootoday/components/core/inline/_figure.scss +3 -0
- data/_sass/modootoday/components/core/inline/_hero.scss +3 -0
- data/_sass/modootoday/components/core/inline/_reveal.scss +10 -0
- data/_sass/modootoday/components/lists/_lists.scss +16 -0
- data/_sass/modootoday/components/section/showcase/_card.scss +3 -0
- data/_sass/modootoday/components/section/structure/_split.scss +14 -0
- data/_sass/modootoday.scss +2 -0
- data/assets/css/modootoday/lists.scss +8 -0
- data/assets/css/modootoday/structure/split.scss +7 -0
- data/i18n/glossary.yml +3 -0
- data/lib/modootoday/check/a11y/illustration.rb +24 -0
- data/lib/modootoday/check/cli.rb +3 -2
- data/lib/modootoday/check/component_rules.rb +3 -1
- data/lib/modootoday/check/i18n.rb +43 -0
- data/lib/modootoday/check/page_sections.rb +13 -6
- data/lib/modootoday/check/page_syntax.rb +6 -3
- data/lib/modootoday/check/pages.rb +1 -0
- data/lib/modootoday/check/site_config.rb +15 -1
- data/lib/modootoday/check/structured_data.rb +13 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 497fb07373c85ca822bcf41f91d4d0703a01209ecaa819b9b7ac7ed98471e1cd
|
|
4
|
+
data.tar.gz: b71c8b2a29a3b01a081330e0d09c0db0233b3a6f2d53224ffa5bad8f65f6c167
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed3f80481897f18f963d7cc0bc3874bb9c80aaa2d5cb4e2cb75a2ffd9150cae1cd276d14f50239a380206c5eb1c9815a58353087cdc58ebe087de17f8ad5ae4b
|
|
7
|
+
data.tar.gz: 036c0ae7ee9ed578162fda1812f2ff3e51dacb39619d56e6e006278ac351597f0f47d78da59e95aeb7b4756f33049f6bc5c292f46e947bb55b565313a1c9faa6
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,33 @@ The content rules have their own version header (`md-components v1`) in [RULES.m
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.1.1] - 2026-10-31
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Release workflow: after the gem is pushed to RubyGems, a GitHub Release is created for the tag with its `CHANGELOG.md` entry as the notes (`script/release-notes`); skipped when the Release already exists.
|
|
14
|
+
- `mt-flat-list`: put it on an ancestor of an unclassed Markdown list that a layout makes a grid or flex row (`.c-body > ul`) to drop the gap between list items (RULES.md §6, Customize).
|
|
15
|
+
- `badge: bottom` on a `c: features` section (`.mt-badge-bottom`): a status badge at the end of a card item sits at the card's bottom edge, so badges line up across a row.
|
|
16
|
+
- `reveal: true` on `hero:` or a section item (`.mt-reveal`): a CSS-only fade-in on scroll, inside `@supports (animation-timeline: view())` and `prefers-reduced-motion: no-preference`. Without support, or when the reader prefers less motion, the content is shown as is. No script.
|
|
17
|
+
- Optional list styles: `modootoday.lists: {link_chips: true, titled_items: true}` turns link-only lists on plain sections and pages into `ul.mt-chips` and `- **Title**: text` items into `strong.mt-item-title` + `span.mt-item-sep`; `hero: {checks: true}` makes the hero's first list a row of ✓ marks (`--mt-ok`). They use a new `lists` sheet (under 1.25 KiB) linked only where used; core CSS is unchanged. The hero lead paragraph gets `.mt-hero-lead`.
|
|
18
|
+
- `decor: <include>` on `hero:` or a section item: an `aria-hidden` ornament in `.mt-section-decor`, placed in the top end corner. `modootoday-check` reports a missing include.
|
|
19
|
+
- `.mt-illustration` convention: `figure[role=img]` with a non-empty `aria-label` and an optional `.mt-illustration-tag` badge; `modootoday-check` reports any other markup in the built site.
|
|
20
|
+
- `ref:` in front matter links translations that live under different paths: `hreflang` and the language switcher use it, and `modootoday/link.html` with `ref=` gives that page's URL in the current language, or in the default language. `modootoday-check` reports a `ref=` that no page defines.
|
|
21
|
+
- `modootoday.full_languages` and `modootoday-check --i18n-pages`: warnings for default-language pages with no translation in those languages; `--strict` makes them fail.
|
|
22
|
+
- `c: split` section: text and its `visual:` include side by side from 48rem, stacked below; params `side: start|end` and `ratio: "1:1"|"5:7"`, inner wrappers `.mt-section-in`, `.mt-section-body`, `.mt-section-visual` (split only, so other sections keep their markup), its own section sheet. `modootoday-check` requires `visual:` on a split.
|
|
23
|
+
- `visual:` include: any other key on the section item reaches the include as `include.section.<key>`, and `modootoday-check` accepts such keys on a section that has `visual:`.
|
|
24
|
+
- Docs: moving from `jekyll-seo-tag` to the kit's SEO tags (Migrate), and what to run when `modootoday-check` is not on `PATH` after `gem install` (Install).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Brand: the visible site name is now **modoo.today theme** (Korean **모두의오늘 테마**, Japanese **modoo.today テーマ**, other languages localized) in the docs header, `<title>`, `og:site_name`, JSON-LD and breadcrumbs, so it is not confused with the modoo.today service. A new optional `site_title` in `_data/i18n/<lang>.yml` sets the header name per language and falls back to `site.title`. The gem name, repository paths, CSS classes, config keys and `modootoday-check` are unchanged.
|
|
29
|
+
- Size budgets have a little more headroom (QA, `qa/audit/config.mjs`): core CSS sheet 24 → 27 KiB, core JS 10 → 11 KiB, CSS one page links 32 → 35 KiB, `loading.css` 2 → 2.5 KiB, `figure.css` 1 → 1.25 KiB, each renderer script 2 → 2.5 KiB. Section sheets stay at 2 KiB. The built sizes did not grow (core CSS 24531 B, core JS 10227 B).
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Checker: specfold value markers with arguments after the name (`<!-- spec:graph format=mermaid source=tutorial -->`, `<!-- spec:count rows="All commands" -->`) are no longer reported as HTML comments (RULES.md, HTML comments row). The HTML comment error now quotes the first comment it found.
|
|
34
|
+
- Checker: JSON-LD between the `jekyll-seo-tag` comments (sites with `seo: false` that bring the plugin) is checked only for valid JSON and reported as a warning, so its `WebPage` without `name` is no longer an error; the kit's own block is still checked in full and not counted as a second block (Structured data).
|
|
35
|
+
|
|
9
36
|
## [1.1.0] - 2026-10-31
|
|
10
37
|
|
|
11
38
|
### Added
|
|
@@ -200,6 +227,7 @@ Internal development milestones, never released. They are all part of 1.0.0.
|
|
|
200
227
|
- Example: `sass.silence_deprecations: [import]` for Dart Sass; `llms.txt` per language generated instead of hand-written.
|
|
201
228
|
- Raw `<name>.md` copies in `_site` on GitHub Pages: caused by content files without front matter (rendered by `jekyll-optional-front-matter` and also copied). Front matter is now required and checked.
|
|
202
229
|
|
|
203
|
-
[Unreleased]: https://github.com/modootoday/jekyll-theme-modootoday/compare/v1.1.
|
|
230
|
+
[Unreleased]: https://github.com/modootoday/jekyll-theme-modootoday/compare/v1.1.1...HEAD
|
|
231
|
+
[1.1.1]: https://github.com/modootoday/jekyll-theme-modootoday/releases/tag/v1.1.1
|
|
204
232
|
[1.1.0]: https://github.com/modootoday/jekyll-theme-modootoday/releases/tag/v1.1.0
|
|
205
233
|
[1.0.0]: https://github.com/modootoday/jekyll-theme-modootoday/releases/tag/v1.0.0
|
data/README.ko.md
CHANGED
|
@@ -38,7 +38,7 @@ Gemfile 없이 GitHub Pages에서(`remote_theme:`):
|
|
|
38
38
|
|
|
39
39
|
```yaml
|
|
40
40
|
# _config.yml
|
|
41
|
-
remote_theme: modootoday/jekyll-theme-modootoday@v1.1.
|
|
41
|
+
remote_theme: modootoday/jekyll-theme-modootoday@v1.1.1
|
|
42
42
|
plugins:
|
|
43
43
|
- jekyll-remote-theme
|
|
44
44
|
```
|
|
@@ -79,6 +79,7 @@ bundle exec modootoday-check . _site
|
|
|
79
79
|
| `--schema-recommended` | also warn about schema.org properties Google Search recommends (author, image, dates, ...) that a JSON-LD node lacks |
|
|
80
80
|
| `--strict` | warnings fail the run |
|
|
81
81
|
| `--i18n` | `_data/i18n/<lang>.yml` against the theme registry (`i18n/en.yml` in the gem): unknown keys, `%{name}` placeholder mismatches, and pages marked `translation: pending` |
|
|
82
|
+
| `--i18n-pages` | warn about default-language pages with no translation in a `modootoday.full_languages` language (the page with the same `ref:`, else the same path under `<lang>/`); with `--strict` they fail |
|
|
82
83
|
| `--i18n-init=LANG,...` | copy the theme's catalogs (`i18n/<lang>.yml`, 23 languages) into `SRC/_data/i18n/` as a starting point for overrides (optional; the theme already uses them), and list keys an existing catalog lacks |
|
|
83
84
|
| `--gh` | also render each page with `gh api markdown` (network, `gh` login) |
|
|
84
85
|
| `--help, -h` | print usage and options (`--help=markdown` prints the README table) |
|
data/README.md
CHANGED
|
@@ -35,7 +35,7 @@ On GitHub Pages without a Gemfile (`remote_theme:`):
|
|
|
35
35
|
|
|
36
36
|
```yaml
|
|
37
37
|
# _config.yml
|
|
38
|
-
remote_theme: modootoday/jekyll-theme-modootoday@v1.1.
|
|
38
|
+
remote_theme: modootoday/jekyll-theme-modootoday@v1.1.1
|
|
39
39
|
plugins:
|
|
40
40
|
- jekyll-remote-theme
|
|
41
41
|
```
|
|
@@ -76,6 +76,7 @@ Walkthrough: [Write your first page](https://modootoday.github.io/jekyll-theme-m
|
|
|
76
76
|
| `--schema-recommended` | also warn about schema.org properties Google Search recommends (author, image, dates, ...) that a JSON-LD node lacks |
|
|
77
77
|
| `--strict` | warnings fail the run |
|
|
78
78
|
| `--i18n` | `_data/i18n/<lang>.yml` against the theme registry (`i18n/en.yml` in the gem): unknown keys, `%{name}` placeholder mismatches, and pages marked `translation: pending` |
|
|
79
|
+
| `--i18n-pages` | warn about default-language pages with no translation in a `modootoday.full_languages` language (the page with the same `ref:`, else the same path under `<lang>/`); with `--strict` they fail |
|
|
79
80
|
| `--i18n-init=LANG,...` | copy the theme's catalogs (`i18n/<lang>.yml`, 23 languages) into `SRC/_data/i18n/` as a starting point for overrides (optional; the theme already uses them), and list keys an existing catalog lacks |
|
|
80
81
|
| `--gh` | also render each page with `gh api markdown` (network, `gh` login) |
|
|
81
82
|
| `--help, -h` | print usage and options (`--help=markdown` prints the README table) |
|
data/RULES.md
CHANGED
|
@@ -14,6 +14,10 @@ Every content page starts with front matter; an empty block (`---` then `---`) i
|
|
|
14
14
|
|---|---|---|---|
|
|
15
15
|
| Alerts (5) | top-level quote whose first line is exactly `> [!NOTE]` (TIP/IMPORTANT/WARNING/CAUTION; any case), body on the following `>` lines. The body may start with a paragraph, a blank `>` line, a list, a code block or a `###` heading. Alerts are a **GitHub extension outside the GFM spec**; other parsers show a plain quote | `_includes/modootoday/markdown/components.html` converts kramdown's `<p>[!TYPE]` + body, standalone `<p>[!TYPE]</p>` and `[!TYPE]<br />` (trailing spaces) into `blockquote.mt-callout.mt-callout-<type>[role=note]` with a localised title | quote / GitHub alert / source |
|
|
16
16
|
| Sections | `# Title`, lead paragraph, link-only paragraph (CTA), then `## Section`; front matter `sections:` | `doc` layout → `_includes/modootoday/markdown/sections.html`: with `sections:` the part before the first `##` is `section.mt-hero` and item *i* wraps the *i*-th **top-level** `##` in `section.mt-section` (an `h2` nested in a quote, list or alert never splits); without it, one `div.mt-prose` | plain document |
|
|
17
|
+
| Section decor | front matter `decor: <include>` on `hero:` or a section item | the include inside `div.mt-section-decor[aria-hidden=true]` at the end of the section, which gets `.mt-has-decor` | not shown |
|
|
18
|
+
| List styles (optional) | `modootoday.lists: {link_chips, titled_items}`; `hero: {checks: true}` | plain sections and pages: link-only list → `ul.mt-chips`, `- **Title**: text` → `strong.mt-item-title` + `span.mt-item-sep`; hero: `.mt-hero-checks`; first `p` after the `h1` → `p.mt-hero-lead` | plain lists |
|
|
19
|
+
| Scroll reveal | front matter `reveal: true` on `hero:` or a section item | `.mt-reveal` on the section; CSS-only fade-in on scroll inside `@supports (animation-timeline: view())` and `prefers-reduced-motion: no-preference` | shown as is |
|
|
20
|
+
| Card badge at the bottom | `badge: bottom` on a `c: features` item | `.mt-badge-bottom` on the section; a `.mt-badge` that is a direct child of a card sits at its bottom edge | badge after the text |
|
|
17
21
|
| Section mapping | each `sections:` item is a string `name` or `{c: component, name: key, ...params}`. No implicit mapping. Item count ≠ top-level `## ` count is a checker error; setext `---` headings, `##` in quotes/alerts/list items, `##` indented 1–3 spaces and `##` inside HTML comments are checker errors | `data-section`=name, `data-c`=c, class `mt-c-<c>` | none |
|
|
18
22
|
| Card grid | under `##`, list items `- **Title** — text` or `- **Title**: text` | CSS only | list |
|
|
19
23
|
| CTA buttons | every link-only paragraph in `section.mt-hero` and in `c: cta` sections; the first link is primary. Separator text such as `·` between links is a text node, so the paragraph still counts as link-only | CSS `p:has(> a):not(:has(> :not(a)))` | links |
|
|
@@ -39,7 +43,7 @@ Every content page starts with front matter; an empty block (`---` then `---`) i
|
|
|
39
43
|
| Progress | `` `progress:60` `` (whole number 0–100) | `span.mt-progress` > `progress` + value text (i18n `progress.label`) | out of range is a checker error |
|
|
40
44
|
| Embed | a paragraph holding only `` `embed:https://… Title` `` | `div.mt-embed` > lazy `iframe[title]` (16:9 reserved) | non-https is a checker error |
|
|
41
45
|
| Loading / skeleton | `` `loading:spinner` ``, `` `loading:bar` ``, `` `skeleton:text` `` / `card` / `image` / `avatar` / `row` | `span.mt-spinner`, `span.mt-topbar`, `span.mt-skeleton` with `role=status`, `aria-busy` and i18n `loading.label`; optional `loading` sheet; reduced motion, forced colors and RTL | unknown variants are checker errors |
|
|
42
|
-
| File tree / Details / FAQ / Params / Link cards / Quote / Gallery / Pricing / Subscribe | `c: filetree` (nested list), `c: details` and `c: faq` (`###` per item), `c: params` (table), `c: linkcards` (link-first list), `c: quote` (quote ending in `— name`), `c: gallery` (tight image list), `c: pricing` (`###` per plan, param `recommended`), `c: subscribe` (text; form posts to `modootoday.subscribe.action`) | per-component markup listed in docs api.md; each has its own sheet | gallery images need alt; `recommended` must be in range; subscribe action must be https |
|
|
46
|
+
| File tree / Details / FAQ / Params / Link cards / Quote / Gallery / Pricing / Subscribe / Split | `c: filetree` (nested list), `c: details` and `c: faq` (`###` per item), `c: params` (table), `c: linkcards` (link-first list), `c: quote` (quote ending in `— name`), `c: gallery` (tight image list), `c: pricing` (`###` per plan, param `recommended`), `c: subscribe` (text; form posts to `modootoday.subscribe.action`), `c: split` (text beside its `visual:`, params `side`, `ratio`; the only section with inner wrappers) | per-component markup listed in docs api.md; each has its own sheet | gallery images need alt; `recommended` must be in range; subscribe action must be https; split needs `visual:` |
|
|
43
47
|
| Component registry | optional `_data/components.yml`: `name: {params: {key: {allowed: [...], required: bool}}, i18n: [keys...]}` | when present the checker validates `c`, params and i18n keys | — |
|
|
44
48
|
|
|
45
49
|
## 3. Localisation
|
|
@@ -55,7 +59,7 @@ The bans are about **portability**: the same source must look the same on github
|
|
|
55
59
|
| Forbidden | Why | Check |
|
|
56
60
|
|---|---|---|
|
|
57
61
|
| raw HTML (`<div>`, `<details>`, `<kbd>` …) | not portable: GitHub renders some tags (`details`, `kbd`) and strips or escapes others (`script`, `iframe`), kramdown passes everything through; keeps twins readable | checker |
|
|
58
|
-
| HTML comments `<!-- -->` | hidden on GitHub but emitted by kramdown; a `##` inside one shifts section counts. Exceptions: a tool region marker alone on its line, `<!-- tool:name:begin -->` / `<!-- tool:name:end -->` (lowercase, ends in `:begin` or `:end`); a one-line specfold value marker, own-line or inline, `<!-- spec:name -->` / `<!-- /spec:name -->` (lowercase letters, digits, `.`, `_`, `-`, `:`-separated) | checker |
|
|
62
|
+
| HTML comments `<!-- -->` | hidden on GitHub but emitted by kramdown; a `##` inside one shifts section counts. Exceptions: a tool region marker alone on its line, `<!-- tool:name:begin -->` / `<!-- tool:name:end -->` (lowercase, ends in `:begin` or `:end`); a one-line specfold value marker, own-line or inline, `<!-- spec:name -->` / `<!-- /spec:name -->` (lowercase letters, digits, `.`, `_`, `-`, `:`-separated), for example `<!-- spec:count -->12<!-- /spec:count -->`; arguments may follow the name after a space, `<!-- spec:count rows="All commands" -->12<!-- /spec:count -->`, on the same line and without `>`, `--` or `##` | checker |
|
|
59
63
|
| Liquid `{% %}` `{{ }}` | breaks on GitHub and in twins | checker |
|
|
60
64
|
| kramdown IAL/ALD `{: .x}`, `{:toc}` | kramdown-only | checker |
|
|
61
65
|
| header ids `{#id}` | kramdown-only (literal text on GitHub) | checker |
|
|
@@ -114,6 +118,7 @@ Stub and generator details:
|
|
|
114
118
|
- Liquid inside code (`{{ }}`) is still processed by Jekyll before kramdown; such pages need `{% raw %}` on the Jekyll side, which itself shows on GitHub.
|
|
115
119
|
- The stylesheet uses Sass `@import` so it compiles with both Ruby Sass (GitHub Pages) and Dart Sass (Jekyll 4); Dart Sass prints deprecation warnings unless the site sets `sass: {silence_deprecations: [import, global-builtin]}` (jekyll-sass-converter ≥ 3.1). Custom properties holding Sass values must interpolate (`--x: #{$v}`); Ruby Sass prints `$v` literally.
|
|
116
120
|
- Component classes are `mt-*`.
|
|
121
|
+
- Lists without a class get `margin-top: .3em` between items (`:where(:not([class])) > li + li`). A layout or include that turns an unclassed Markdown list into a grid or flex row (for example `.c-body > ul`) puts `mt-flat-list` on an ancestor to drop that gap; a list with any class of its own is already exempt.
|
|
117
122
|
- CTA buttons need `:has()`; without it they stay links.
|
|
118
123
|
|
|
119
124
|
## 7. Design tokens artifact
|
|
@@ -7,7 +7,7 @@ The home crumb uses the home page short_title, then its title. Hidden on the hom
|
|
|
7
7
|
{%- if page.url != _home and page.url != "/" -%}
|
|
8
8
|
{%- assign _hp = site.pages | where: "url", _home | first -%}
|
|
9
9
|
<nav class="mt-breadcrumb" aria-label="{% include modootoday/i18n.html lang=_lang %}{{ mt_t_breadcrumb_label }}"><ol>
|
|
10
|
-
<li><a href="{{ _home | relative_url }}">{{ _hp.short_title | default: _hp.title | default: site.title | default: "Home" }}</a></li>
|
|
10
|
+
<li><a href="{{ _home | relative_url }}">{{ _hp.short_title | default: _hp.title | default: mt_site_title | default: site.title | default: "Home" }}</a></li>
|
|
11
11
|
{%- assign _acc = _home -%}
|
|
12
12
|
{%- for _s in _segs offset: 1 -%}{%- if forloop.index > _start and _s != "" and _s != "index.html" -%}
|
|
13
13
|
{%- assign _acc = _acc | append: _s | append: "/" -%}
|
|
@@ -10,15 +10,16 @@ Jekyll 3.10 / GitHub Pages, so every default lives here (Liquid). Sets mt_* vari
|
|
|
10
10
|
site.modootoday.tokens / tokens_dark semantic token overrides, inline :root CSS
|
|
11
11
|
site.modootoday.sidebar auto | true | false: doc-page sidebar from the nav (default auto: on when the nav has a group)
|
|
12
12
|
site.modootoday.badges false disables status badges (default true)
|
|
13
|
+
site.modootoday.lists {link_chips: true, titled_items: true}: optional list markup (markdown/lists.html, lists sheet)
|
|
13
14
|
{%- endcomment -%}
|
|
14
15
|
{%- assign mt = site.modootoday -%}
|
|
15
|
-
{%- assign mt_all_components = "callout,badge,hero,cta,card,tabs,code-copy,nav,sidebar,page-actions,pagination,theme-toggle,breadcrumb,toc,accordion,steps,figure,timeline,kbd,search,code,footnotes,progress,embed,banner,filetree,details,faq,params,linkcards,quote,gallery,pricing,subscribe,loading,figure-svg" | split: "," -%}
|
|
16
|
+
{%- assign mt_all_components = "callout,badge,hero,cta,card,tabs,code-copy,nav,sidebar,page-actions,pagination,theme-toggle,breadcrumb,toc,accordion,steps,figure,timeline,kbd,search,code,footnotes,progress,embed,banner,filetree,details,faq,params,linkcards,quote,gallery,pricing,subscribe,split,loading,figure-svg,lists,reveal" | split: "," -%}
|
|
16
17
|
{%- comment -%}Sass partials by context (components/<group>/_<name>.scss). Core: always in assets/css/modootoday.css.
|
|
17
18
|
Section sheets: assets/css/modootoday/<group>/<name>.css, linked when a page's sections: use c (c:sheet).
|
|
18
19
|
Context sheets: assets/css/modootoday/<name>.css, linked by layout front matter mt_sheets (doc; blog layouts also get assets/css/modootoday-blog.css).{%- endcomment -%}
|
|
19
|
-
{%- assign mt_core_partials = "core/inline/callout,core/inline/badge,core/inline/kbd,core/inline/figure,core/inline/code-copy,core/inline/hero,core/inline/cta,core/inline/code,core/inline/footnotes,core/inline/progress,core/inline/embed,core/chrome/nav,core/chrome/theme-toggle,core/chrome/breadcrumb,core/chrome/pagination,core/chrome/banner" | split: "," -%}
|
|
20
|
-
{%- assign mt_section_sheets = "cta:showcase/cta,features:showcase/card,linkcards:showcase/linkcards,quote:showcase/quote,gallery:showcase/gallery,pricing:showcase/pricing,subscribe:showcase/subscribe,tabs:structure/tabs,accordion:structure/accordion,steps:structure/steps,timeline:structure/timeline,filetree:structure/filetree,details:structure/details,faq:structure/faq,params:structure/params" | split: "," -%}
|
|
21
|
-
{%- assign mt_context_sheets = "doc:sidebar|toc|page-actions,search:search,loading:loading,figure:figure-svg" | split: "," -%}
|
|
20
|
+
{%- assign mt_core_partials = "core/inline/callout,core/inline/badge,core/inline/kbd,core/inline/figure,core/inline/code-copy,core/inline/hero,core/inline/reveal,core/inline/cta,core/inline/code,core/inline/footnotes,core/inline/progress,core/inline/embed,core/chrome/nav,core/chrome/theme-toggle,core/chrome/breadcrumb,core/chrome/pagination,core/chrome/banner" | split: "," -%}
|
|
21
|
+
{%- assign mt_section_sheets = "cta:showcase/cta,features:showcase/card,linkcards:showcase/linkcards,quote:showcase/quote,gallery:showcase/gallery,pricing:showcase/pricing,subscribe:showcase/subscribe,tabs:structure/tabs,accordion:structure/accordion,steps:structure/steps,timeline:structure/timeline,filetree:structure/filetree,details:structure/details,faq:structure/faq,params:structure/params,split:structure/split" | split: "," -%}
|
|
22
|
+
{%- assign mt_context_sheets = "doc:sidebar|toc|page-actions,search:search,loading:loading,figure:figure-svg,lists:lists" | split: "," -%}
|
|
22
23
|
{%- assign mt_components = mt_all_components -%}
|
|
23
24
|
{%- if mt.components -%}{%- assign mt_components = mt.components -%}{%- endif -%}
|
|
24
25
|
{%- assign mt_color_scheme = "auto" -%}
|
|
@@ -3,6 +3,7 @@ SEO and theme-init head tags (needs modootoday/config.html first). Liquid only,
|
|
|
3
3
|
site.modootoday.seo false drops canonical, hreflang and Open Graph (use jekyll-seo-tag instead)
|
|
4
4
|
site.modootoday.hreflang true keeps the hreflang alternates when seo is false (default: follows seo)
|
|
5
5
|
site.modootoday.languages list of language codes for hreflang, e.g. [en, ko]; site.lang is unprefixed, others live under /<lang>/
|
|
6
|
+
(a page with front matter ref: links the pages sharing that ref instead, whatever their paths)
|
|
6
7
|
site.modootoday.feed true adds the Atom link to /feed.xml, or /<lang>/feed.xml when that page exists (jekyll-feed or layout: feed)
|
|
7
8
|
site.modootoday.csp strict loads the pre-paint theme script from a file instead of inline
|
|
8
9
|
site.modootoday.favicon brand links the theme's modootoday mark (SVG, 32px PNG, apple-touch); a path links your own icon
|
|
@@ -39,7 +40,8 @@ SEO and theme-init head tags (needs modootoday/config.html first). Liquid only,
|
|
|
39
40
|
{%- if _mt_plang != _mt_def -%}{%- assign _mt_pre = "/" | append: _mt_plang -%}{%- assign _mt_base = page.url | remove_first: _mt_pre -%}{%- endif -%}
|
|
40
41
|
{%- unless mt_page_urls -%}{%- assign mt_page_urls = site.pages | map: "url" | join: "|" | prepend: "|" | append: "|" -%}{%- endunless -%}
|
|
41
42
|
{%- for _l in _mt_langs -%}
|
|
42
|
-
{%- if
|
|
43
|
+
{%- if page.ref -%}{%- include modootoday/ref-url.html ref=page.ref lang=_l exact=true -%}{%- assign _mt_alt = mt_ref_url | default: "/-none-/" -%}
|
|
44
|
+
{%- elsif _l == _mt_def -%}{%- assign _mt_alt = _mt_base -%}{%- else -%}{%- assign _mt_alt = "/" | append: _l | append: _mt_base -%}{%- endif -%}
|
|
43
45
|
{%- assign _mt_key = "|" | append: _mt_alt | append: "|" -%}
|
|
44
46
|
{%- if mt_page_urls contains _mt_key %}
|
|
45
47
|
<link rel="alternate" hreflang="{{ _l }}" href="{{ _mt_alt | absolute_url }}">
|
|
@@ -68,7 +70,7 @@ SEO and theme-init head tags (needs modootoday/config.html first). Liquid only,
|
|
|
68
70
|
<meta property="og:description" content="{{ page.description | default: site.description | strip_html | normalize_whitespace | escape }}">
|
|
69
71
|
{%- endif -%}
|
|
70
72
|
{%- if site.title %}
|
|
71
|
-
<meta property="og:site_name" content="{{ site.title | escape }}">
|
|
73
|
+
<meta property="og:site_name" content="{{ mt_site_title | default: site.title | escape }}">
|
|
72
74
|
{%- endif -%}
|
|
73
75
|
{%- if site.url %}
|
|
74
76
|
<meta property="og:url" content="{{ _mt_url }}">
|
|
@@ -4,7 +4,7 @@ is a page, then the page. Not printed on the home page or a /<lang>/ home.{%- en
|
|
|
4
4
|
{%- if _ld_segs[1] == _ld_lang and _ld_lang != site.lang -%}{%- assign _ld_home = "/" | append: _ld_lang | append: "/" -%}{%- assign _ld_start = 1 -%}{%- endif -%}
|
|
5
5
|
{%- if page.url != _ld_home and page.url != "/" -%}
|
|
6
6
|
{%- assign _ld_hp = site.pages | where: "url", _ld_home | first -%}{%- assign _ld_n = 1 -%}
|
|
7
|
-
,{"@type":"BreadcrumbList","@id":{{ _ld_url | append: "#breadcrumb" | jsonify }},"itemListElement":[{"@type":"ListItem","position":1,"name":{{ _ld_hp.short_title | default: _ld_hp.title | default: site.title | default: "Home" | strip_html | jsonify }},"item":{{ _ld_home | absolute_url | jsonify }}}
|
|
7
|
+
,{"@type":"BreadcrumbList","@id":{{ _ld_url | append: "#breadcrumb" | jsonify }},"itemListElement":[{"@type":"ListItem","position":1,"name":{{ _ld_hp.short_title | default: _ld_hp.title | default: mt_site_title | default: site.title | default: "Home" | strip_html | jsonify }},"item":{{ _ld_home | absolute_url | jsonify }}}
|
|
8
8
|
{%- assign _ld_acc = _ld_home -%}
|
|
9
9
|
{%- for _s in _ld_segs offset: 1 -%}{%- if forloop.index > _ld_start and _s != "" and _s != "index.html" -%}
|
|
10
10
|
{%- assign _ld_acc = _ld_acc | append: _s | append: "/" -%}
|
|
@@ -3,7 +3,7 @@ Defaults: Organization named site.title; logo from publisher.logo, or the brand
|
|
|
3
3
|
{%- assign _ld_p = _ld.publisher -%}
|
|
4
4
|
{%- assign _ld_pt = _ld_p.type | default: "Organization" -%}
|
|
5
5
|
{%- assign _ld_pl = _ld_p.logo -%}{%- if _ld_pl == nil and site.modootoday.logo == "brand" -%}{%- assign _ld_pl = "/assets/modootoday/apple-touch-icon.png" -%}{%- elsif _ld_pl == nil -%}{%- assign _ld_pl = site.modootoday.logo -%}{%- endif -%}
|
|
6
|
-
,{"@type":{{ _ld_pt | jsonify }},"@id":{{ _ld_root | append: "#publisher" | jsonify }},"name":{{ _ld_p.name | default: site.title | default: _ld_title | jsonify }},"url":{{ _ld_p.url | default: "/" | absolute_url | jsonify }}
|
|
6
|
+
,{"@type":{{ _ld_pt | jsonify }},"@id":{{ _ld_root | append: "#publisher" | jsonify }},"name":{{ _ld_p.name | default: mt_site_title | default: site.title | default: _ld_title | jsonify }},"url":{{ _ld_p.url | default: "/" | absolute_url | jsonify }}
|
|
7
7
|
{%- if _ld_pl -%}{%- assign _ld_plu = _ld_pl | absolute_url -%}
|
|
8
8
|
{%- if _ld_pt == "Person" %},"image":{{ _ld_plu | jsonify }}{% else %},"logo":{"@type":"ImageObject","url":{{ _ld_plu | jsonify }}}{% endif -%}
|
|
9
9
|
{%- endif -%}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{%- comment -%}WebSite node (#website). site.modootoday.schema.search_url (a URL with {search_term_string}) adds a SearchAction.{%- endcomment -%}
|
|
2
|
-
{"@type":"WebSite","@id":{{ _ld_root | append: "#website" | jsonify }},"url":{{ _ld_root | jsonify }},"name":{{ site.title | default: _ld_title | jsonify }}
|
|
2
|
+
{"@type":"WebSite","@id":{{ _ld_root | append: "#website" | jsonify }},"url":{{ _ld_root | jsonify }},"name":{{ mt_site_title | default: site.title | default: _ld_title | jsonify }}
|
|
3
3
|
{%- if site.description %},"description":{{ site.description | strip_html | normalize_whitespace | jsonify }}{% endif -%}
|
|
4
4
|
,"inLanguage":{{ site.lang | default: "en" | jsonify }},"publisher":{"@id":{{ _ld_root | append: "#publisher" | jsonify }}}
|
|
5
5
|
{%- if _ld.search_url -%}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{%- comment -%}
|
|
2
|
-
Language switcher, built from modootoday.languages (the same alternates as the hreflang links
|
|
2
|
+
Language switcher, built from modootoday.languages (the same alternates as the hreflang links; pages with ref: use the
|
|
3
|
+
page sharing that ref in each language).
|
|
3
4
|
Each language links to this page's translation when it exists, else to that language's home page.
|
|
4
5
|
Opt in with modootoday.language_switcher: header | footer, or include it in your own footer-custom.html.
|
|
5
6
|
Label text: language (the language's own name) and languages.label (modootoday/i18n.html: site _data/i18n, theme catalog, English).
|
|
@@ -16,7 +17,8 @@
|
|
|
16
17
|
{%- unless mt_page_urls -%}{%- assign mt_page_urls = site.pages | map: "url" | join: "|" | prepend: "|" | append: "|" -%}{%- endunless -%}
|
|
17
18
|
{%- capture _ls_items -%}
|
|
18
19
|
{%- for _l in site.modootoday.languages -%}
|
|
19
|
-
{%- if
|
|
20
|
+
{%- if page.ref -%}{%- include modootoday/ref-url.html ref=page.ref lang=_l exact=true -%}{%- assign _ls_alt = mt_ref_url | default: "/-none-/" -%}
|
|
21
|
+
{%- elsif _l == _ls_def -%}{%- assign _ls_alt = _ls_base -%}{%- else -%}{%- assign _ls_alt = "/" | append: _l | append: _ls_base -%}{%- endif -%}
|
|
20
22
|
{%- assign _ls_key = "|" | append: _ls_alt | append: "|" -%}
|
|
21
23
|
{%- unless mt_page_urls contains _ls_key -%}{%- if _l == _ls_def -%}{%- assign _ls_alt = "/" -%}{%- else -%}{%- assign _ls_alt = "/" | append: _l | append: "/" -%}{%- endif -%}{%- endunless -%}
|
|
22
24
|
{%- capture _ls_name -%}{%- include modootoday/i18n/name.html code=_l -%}{%- endcapture -%}{%- assign _ls_name = site.data.i18n[_l].language | default: _ls_name -%}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
{%- comment -%}URL for include.url: full URLs as they are, site paths through relative_url (absolute=true: absolute_url).
|
|
2
|
-
A bare "#" sample link stays "#" (absolute=true: this page's absolute URL, for JSON-LD).
|
|
3
|
-
|
|
2
|
+
A bare "#" sample link stays "#" (absolute=true: this page's absolute URL, for JSON-LD).
|
|
3
|
+
include.ref instead of url: the page with that front matter ref: in this page's language (lang= to choose another),
|
|
4
|
+
else the default-language one (modootoday/ref-url.html); modootoday-check rejects a ref no page defines.{%- endcomment -%}
|
|
5
|
+
{%- if include.ref -%}{%- include modootoday/ref-url.html ref=include.ref lang=include.lang -%}{%- if include.absolute -%}{{ mt_ref_url | absolute_url }}{%- else -%}{{ mt_ref_url | relative_url }}{%- endif -%}
|
|
6
|
+
{%- elsif include.url == "#" and include.absolute -%}{{ page.url | absolute_url }}{%- elsif include.url == "#" or include.url contains "://" or include.url contains "mailto:" or include.url contains "tel:" -%}{{ include.url }}{%- elsif include.absolute -%}{{ include.url | absolute_url }}{%- else -%}{{ include.url | relative_url }}{%- endif -%}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
md-components v1 — optional list styles (site.modootoday.lists; the lists sheet styles them). Prints include.html with:
|
|
3
|
+
link_chips: true a list whose every item is one link and nothing else → ul.mt-chips (a row of chips)
|
|
4
|
+
titled_items: true an item that starts with **Title**: → li > strong.mt-item-title + span.mt-item-sep, then the text
|
|
5
|
+
Applied to the hero, to sections without c: and to pages without sections; component sections keep their own lists.
|
|
6
|
+
{%- endcomment -%}
|
|
7
|
+
{%- assign _lh = include.html -%}
|
|
8
|
+
{%- if site.modootoday.lists.titled_items == true and _lh contains "<li><strong>" -%}
|
|
9
|
+
{%- assign _lp = _lh | split: "<li><strong>" -%}
|
|
10
|
+
{%- capture _lh -%}{{ _lp[0] }}{%- for _x in _lp offset:1 -%}
|
|
11
|
+
{%- assign _t = _x | split: "</strong>: " -%}{%- assign _tt = _t[0] -%}
|
|
12
|
+
{%- if _t.size > 1 -%}{%- unless _tt contains "</li>" or _tt contains "<li" -%}{%- assign _ok = true -%}{%- else -%}{%- assign _ok = false -%}{%- endunless -%}{%- else -%}{%- assign _ok = false -%}{%- endif -%}
|
|
13
|
+
{%- if _ok -%}<li><strong class="mt-item-title">{{ _tt }}</strong><span class="mt-item-sep">: </span>{{ _x | remove_first: _tt | remove_first: "</strong>: " }}{%- else -%}<li><strong>{{ _x }}{%- endif -%}
|
|
14
|
+
{%- endfor -%}{%- endcapture -%}
|
|
15
|
+
{%- endif -%}
|
|
16
|
+
{%- if site.modootoday.lists.link_chips == true and _lh contains "<ul>" -%}
|
|
17
|
+
{%- assign _nl = "
|
|
18
|
+
" -%}{%- assign _us = "<ul>" | append: _nl -%}
|
|
19
|
+
{%- assign _lp = _lh | split: _us -%}
|
|
20
|
+
{%- capture _lh -%}{{ _lp[0] }}{%- for _x in _lp offset:1 -%}
|
|
21
|
+
{%- assign _in = _x | split: "</ul>" | first -%}
|
|
22
|
+
{%- assign _n1 = _in | split: "<li>" | size -%}{%- assign _n2 = _in | split: "<li><a " | size -%}{%- assign _n3 = _in | split: "</a></li>" | size -%}{%- assign _n4 = _in | split: "<a " | size -%}
|
|
23
|
+
{%- if _n1 > 1 and _n1 == _n2 and _n1 == _n3 and _n1 == _n4 -%}<ul class="mt-chips">{{ _nl }}{%- else -%}{{ _us }}{%- endif -%}{{ _x }}
|
|
24
|
+
{%- endfor -%}{%- endcapture -%}
|
|
25
|
+
{%- endif -%}
|
|
26
|
+
{{- _lh -}}
|
|
@@ -7,7 +7,15 @@ Only top-level h2 split: kramdown prints them at column 0 ("\n<h2 "), nested one
|
|
|
7
7
|
alert) are indented and stay inside their section. modootoday-check rejects nested/setext/indented ##.
|
|
8
8
|
Item: "name" or {c: component, name: key, ...params}. c: tabs → data-tabs, c: cta → (on the section, or on its [data-mt-result] element when it holds one, so a showcase box only frames the result).
|
|
9
9
|
visual: <name> on an item (or include.hero.visual for the hero) appends the site's
|
|
10
|
-
_includes/sections/<name>.html at the end of that section, called with section=<item> (hero=<hero>)
|
|
10
|
+
_includes/sections/<name>.html at the end of that section, called with section=<item> (hero=<hero>); every other key
|
|
11
|
+
on the item (e.g. scene: 2) reaches the include as include.section.<key>.
|
|
12
|
+
c: split wraps the section in div.mt-section-in > div.mt-section-body (h2 and text) + div.mt-section-visual (the visual
|
|
13
|
+
include): two columns from 48rem (side: start|end puts the visual first or last, ratio: "1:1"|"5:7" text:visual), one below.
|
|
14
|
+
Only split gets the wrappers, so child selectors of the other components keep working.
|
|
15
|
+
decor: <name> (item or hero) adds _includes/sections/<name>.html in div.mt-section-decor[aria-hidden=true], placed in
|
|
16
|
+
the section's top end corner (section gets .mt-has-decor); for ornaments only, never content.
|
|
17
|
+
The hero's first p after the h1 gets .mt-hero-lead; hero checks: true adds .mt-hero-checks (its first ul is a ✓ row, lists sheet).
|
|
18
|
+
site.modootoday.lists (link_chips, titled_items) runs markdown/lists.html on the hero, plain sections and section-less pages.
|
|
11
19
|
modootoday-check fails when the item count differs from the h2 count.
|
|
12
20
|
{%- endcomment -%}
|
|
13
21
|
{%- assign _lang = include.lang | default: site.lang | default: "en" -%}
|
|
@@ -23,21 +31,27 @@ modootoday-check fails when the item count differs from the h2 count.
|
|
|
23
31
|
{%- if _fparts.size > 1 -%}{%- assign _notes = include.content | remove_first: _main | strip -%}{%- endif -%}
|
|
24
32
|
{%- assign _parts = _main | prepend: _nl | split: _sep -%}
|
|
25
33
|
{%- assign mt_c_transforms = "|filetree|linkcards|details|faq|params|quote|gallery|pricing|subscribe|" -%}
|
|
26
|
-
{%- assign _p0 = _parts[0] -%}{%- capture
|
|
27
|
-
|
|
34
|
+
{%- assign _p0 = _parts[0] -%}{%- if site.modootoday.lists -%}{%- capture _p0 %}{% include modootoday/markdown/lists.html html=_p0 %}{% endcapture -%}{%- endif -%}
|
|
35
|
+
{%- capture _hero %}{% include modootoday/actions.html html=_p0 %}{% endcapture -%}{%- assign _hl = "</h1>" | append: _nl | append: _nl -%}{%- assign _hlp = _hl | append: "<p>" -%}{%- assign _hlc = _hl | append: '<p class="mt-hero-lead">' -%}{%- assign _hero = _hero | replace_first: _hlp, _hlc -%}
|
|
36
|
+
<section class="mt-hero{% if include.hero.checks == true %} mt-hero-checks{% endif %}{% if include.hero.decor %} mt-has-decor{% endif %}{% if include.hero.reveal == true %} mt-reveal{% endif %}">{{ _hero }}{% if include.hero.visual %}{% include sections/{{ include.hero.visual }}.html section=include.hero %}{% endif %}{% if include.hero.decor %}<div class="mt-section-decor" aria-hidden="true">{% include sections/{{ include.hero.decor }}.html section=include.hero %}</div>{% endif %}</section>
|
|
28
37
|
{%- for _p in _parts offset:1 -%}
|
|
29
38
|
{%- assign _s = include.sections[forloop.index0] -%}
|
|
30
39
|
{%- if _s.name or _s.c -%}{%- assign _n = _s.name -%}{%- assign _cc = _s.c -%}{%- else -%}{%- assign _n = _s -%}{%- assign _cc = nil -%}{%- endif -%}
|
|
31
40
|
{%- assign _body = _p -%}
|
|
41
|
+
{%- if site.modootoday.lists and _cc == nil -%}{%- capture _body %}{% include modootoday/markdown/lists.html html=_p %}{% endcapture -%}{%- endif -%}
|
|
32
42
|
{%- if _cc == 'cta' -%}{%- capture _body %}{% include modootoday/actions.html html=_p %}{% endcapture -%}{%- endif -%}
|
|
33
43
|
{%- if _cc == 'features' -%}{%- assign _body = _body | replace: "</strong> — ", "</strong> " | replace: "</strong> – ", "</strong> " | replace: "</strong> - ", "</strong> " -%}{%- endif -%}
|
|
34
44
|
{%- if _cc and mt_c_transforms contains _cc -%}{%- capture _body %}{% include modootoday/markdown/c/{{ _cc }}.html html=_body s=_s i=forloop.index id=_n %}{% endcapture -%}{%- endif -%}
|
|
35
|
-
<section class="mt-section{% if _cc %} mt-c-{{ _cc }}{% endif %}{% if _cc == 'cta' %}{% unless _body contains 'data-mt-result' %} mt-cta{% endunless %}{% endif %}{% if _s.cols %} mt-cols-{{ _s.cols }}{% endif %}" data-section="{{ _n | default: forloop.index0 }}"{% if _cc %} data-c="{{ _cc }}"{% endif %}{% if _cc == 'tabs' %} data-tabs data-tabs-label="{{ _tl }}"{% endif %}>
|
|
36
|
-
|
|
45
|
+
<section class="mt-section{% if _cc %} mt-c-{{ _cc }}{% endif %}{% if _cc == 'cta' %}{% unless _body contains 'data-mt-result' %} mt-cta{% endunless %}{% endif %}{% if _s.cols %} mt-cols-{{ _s.cols }}{% endif %}{% if _s.decor %} mt-has-decor{% endif %}{% if _s.reveal == true %} mt-reveal{% endif %}{% if _cc == 'features' and _s.badge == 'bottom' %} mt-badge-bottom{% endif %}{% if _cc == 'split' %}{% if _s.side == 'start' %} mt-split-start{% endif %}{% if _s.ratio == '5:7' %} mt-split-5-7{% endif %}{% endif %}" data-section="{{ _n | default: forloop.index0 }}"{% if _cc %} data-c="{{ _cc }}"{% endif %}{% if _cc == 'tabs' %} data-tabs data-tabs-label="{{ _tl }}"{% endif %}>
|
|
46
|
+
{%- if _cc == 'split' %}
|
|
47
|
+
<div class="mt-section-in"><div class="mt-section-body"><h2 {{ _body }}</div>{% if _s.visual %}<div class="mt-section-visual">{% include sections/{{ _s.visual }}.html section=_s %}</div>{% endif %}</div>{% if _s.decor %}<div class="mt-section-decor" aria-hidden="true">{% include sections/{{ _s.decor }}.html section=_s %}</div>{% endif %}</section>
|
|
48
|
+
{%- else %}
|
|
49
|
+
<h2 {{ _body }}{% if _s.visual %}{% include sections/{{ _s.visual }}.html section=_s %}{% endif %}{% if _s.decor %}<div class="mt-section-decor" aria-hidden="true">{% include sections/{{ _s.decor }}.html section=_s %}</div>{% endif %}</section>
|
|
50
|
+
{%- endif -%}
|
|
37
51
|
{%- endfor -%}
|
|
38
52
|
{%- if _notes != "" %}
|
|
39
53
|
<div class="mt-endnotes">{{ _notes }}</div>
|
|
40
54
|
{%- endif -%}
|
|
41
55
|
{%- else -%}
|
|
42
|
-
<div class="mt-prose">{{ include.content }}</div>
|
|
56
|
+
{%- if site.modootoday.lists -%}<div class="mt-prose">{% include modootoday/markdown/lists.html html=include.content %}</div>{%- else -%}<div class="mt-prose">{{ include.content }}</div>{%- endif -%}
|
|
43
57
|
{%- endif -%}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{%- comment -%}Sets mt_ref_url to the URL (site path, before relative_url) of the page whose front matter ref: is include.ref,
|
|
2
|
+
in include.lang (default: this page's lang, then site.lang). Without one in that language it falls back to the
|
|
3
|
+
default-language page, unless include.exact is true; mt_ref_url is nil when nothing matches.
|
|
4
|
+
A page's language is its lang: (front matter or defaults), else site.lang.{%- endcomment -%}
|
|
5
|
+
{%- assign mt_ref_url = nil -%}
|
|
6
|
+
{%- assign _rf_def = site.lang | default: "en" -%}
|
|
7
|
+
{%- assign _rf_lang = include.lang | default: page.lang | default: _rf_def -%}
|
|
8
|
+
{%- assign _rf_pages = site.pages | where: "ref", include.ref -%}
|
|
9
|
+
{%- for _rf_p in _rf_pages -%}{%- assign _rf_l = _rf_p.lang | default: _rf_def -%}{%- if _rf_l == _rf_lang -%}{%- assign mt_ref_url = _rf_p.url -%}{%- break -%}{%- endif -%}{%- endfor -%}
|
|
10
|
+
{%- unless mt_ref_url or include.exact -%}
|
|
11
|
+
{%- for _rf_p in _rf_pages -%}{%- assign _rf_l = _rf_p.lang | default: _rf_def -%}{%- if _rf_l == _rf_def -%}{%- assign mt_ref_url = _rf_p.url -%}{%- break -%}{%- endif -%}{%- endfor -%}
|
|
12
|
+
{%- endunless -%}
|
|
@@ -10,6 +10,7 @@ Stylesheet links (needs modootoday/config.html first). Sets mt_page_c ("|tabs|fa
|
|
|
10
10
|
{%- if mt_components contains "search" and mt_search_index -%}{%- assign mt_page_c = mt_page_c | append: "search|" -%}{%- endif -%}
|
|
11
11
|
{%- if site.modootoday.loading or content contains 'class="mt-spinner' or content contains 'class="mt-skeleton' or content contains 'class="mt-topbar' -%}{%- assign mt_page_c = mt_page_c | append: "loading|" -%}{%- endif -%}
|
|
12
12
|
{%- if content contains 'class="mt-figure mt-figure-svg' -%}{%- assign mt_page_c = mt_page_c | append: "figure|" -%}{%- endif -%}
|
|
13
|
+
{%- if content contains 'class="mt-hero mt-hero-checks' or content contains 'class="mt-chips"' or content contains 'class="mt-item-title"' -%}{%- assign mt_page_c = mt_page_c | append: "lists|" -%}{%- endif -%}
|
|
13
14
|
{%- for _x in layout.mt_css -%}{%- assign mt_page_c = mt_page_c | append: _x | append: "|" -%}{%- endfor -%}
|
|
14
15
|
{%- for _x in page.css -%}{%- assign mt_page_c = mt_page_c | append: _x | append: "|" -%}{%- endfor %}
|
|
15
16
|
{%- comment -%}Blog, news and archive layouts add the separate blog sheet (both modes); front matter blog_css: true opts any page in.{%- endcomment -%}
|
data/_layouts/default.html
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
{%- assign _lang = page.lang | default: site.lang | default: "en" -%}
|
|
4
4
|
{%- include modootoday/config.html -%}
|
|
5
5
|
{%- include modootoday/i18n.html lang=_lang -%}
|
|
6
|
+
{%- comment -%}mt_site_title: the brand name shown in the header, <title>, og:site_name and JSON-LD; site.data.i18n[lang].site_title localises it, else site.title.{%- endcomment -%}
|
|
7
|
+
{%- assign mt_site_title = site.data.i18n[_lang].site_title | default: site.title -%}
|
|
6
8
|
{%- comment -%}mt_home: this language's home (/<lang>/ when that page exists), else the site root; used by the brand link and footers.{%- endcomment -%}
|
|
7
9
|
{%- assign mt_home = "/" -%}{%- assign _def_lang = site.lang | default: "en" -%}
|
|
8
10
|
{%- if _lang != _def_lang -%}{%- assign _lh = "/" | append: _lang | append: "/" -%}{%- assign _lhp = site.pages | where: "url", _lh | first -%}{%- if _lhp -%}{%- assign mt_home = _lh -%}{%- endif -%}{%- endif -%}
|
|
@@ -14,7 +16,7 @@
|
|
|
14
16
|
<head>
|
|
15
17
|
<meta charset="utf-8">
|
|
16
18
|
<meta name="viewport" content="width=device-width, initial-scale=1{% unless site.modootoday.viewport_fit == "auto" %}, viewport-fit=cover{% endunless %}">
|
|
17
|
-
<title>{% if page.title %}{{ page.title }}{% if site.title %} · {{
|
|
19
|
+
<title>{% if page.title %}{{ page.title }}{% if site.title %} · {{ mt_site_title }}{% endif %}{% else %}{{ mt_site_title }}{% endif %}</title>
|
|
18
20
|
{%- if page.description or site.description %}
|
|
19
21
|
<meta name="description" content="{{ page.description | default: site.description | strip_html | normalize_whitespace | escape }}">
|
|
20
22
|
{%- endif %}
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
{%- endif %}
|
|
46
48
|
{%- assign _chrome = true -%}{%- if layout.mt_chrome == false or page.chrome == false -%}{%- assign _chrome = false -%}{%- endif -%}
|
|
47
49
|
{%- if site.title and _chrome %}
|
|
48
|
-
<header class="mt-header"><div class="mt-header-inner"><a class="mt-site-title{% if site.modootoday.logo %} mt-has-logo{% endif %}" href="{{ mt_home | relative_url }}">{% include modootoday/brand/logo.html %}{{
|
|
50
|
+
<header class="mt-header"><div class="mt-header-inner"><a class="mt-site-title{% if site.modootoday.logo %} mt-has-logo{% endif %}" href="{{ mt_home | relative_url }}">{% include modootoday/brand/logo.html %}{{ mt_site_title }}</a>{% include modootoday/nav.html %}{% if mt_components contains "search" and mt_search_index %}<div class="mt-search" role="search" data-index="{{ '/search.json' | relative_url }}" data-lang="{{ site.lang | default: 'en' }}" hidden>{% include modootoday/brand/icon.html name="search" size=16 %}<input type="search" aria-keyshortcuts="/ Control+K Meta+K" aria-controls="mt-search-results" aria-label="{{ mt_t_search_label }}" placeholder="{{ mt_t_search_label }}"><ul class="mt-search-results" id="mt-search-results" aria-live="polite"></ul></div>{% endif %}{% if site.modootoday.language_switcher == "header" %}{% include modootoday/lang-switch.html style="menu" %}{% endif %}{% if mt_components contains "theme-toggle" and mt_theme_toggle %}<button class="mt-theme-toggle" type="button" aria-pressed="false" aria-label="{{ mt_t_theme_toggle }}" title="{{ mt_t_theme_toggle }}" hidden>{% include modootoday/brand/icon.html name="moon" %}{% include modootoday/brand/icon.html name="sun" %}</button>{% endif %}</div></header>
|
|
49
51
|
{%- endif %}
|
|
50
52
|
<main id="mt-main" tabindex="-1" class="mt-main{% if page.full_width %} mt-main-full{% endif %}{% if layout.mt_main %} {{ layout.mt_main }}{% endif %}">
|
|
51
53
|
{% include modootoday/links/content.html html=content %}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
h4 { font-size: 1rem; }
|
|
9
9
|
p, ul, ol, dl { margin: 0 0 1em; }
|
|
10
10
|
:where(:not([class])) > li + li { margin-top: .3em; } // flow lists only: classed grid/flex lists keep item 1 aligned
|
|
11
|
+
.mt-flat-list li + li { margin-top: 0; } // opt-out on an ancestor, for unclassed Markdown lists made grid/flex (.c-body > ul)
|
|
11
12
|
li > ul, li > ol { margin: .3em 0 0; }
|
|
12
13
|
blockquote { margin: 1.25rem 0; padding: .25rem 1rem; color: mt(muted-foreground); border-inline-start: 3px solid mt(border); }
|
|
13
14
|
blockquote > :last-child { margin-bottom: 0; }
|
|
@@ -6,4 +6,7 @@
|
|
|
6
6
|
:root[data-theme="dark"] .mt-figure img { filter: brightness(.85); }
|
|
7
7
|
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .mt-figure img { filter: brightness(.85); } }
|
|
8
8
|
.mt-figure figcaption { margin-top: .6rem; color: mt(muted-foreground); font-size: .875rem; text-align: center; }
|
|
9
|
+
// .mt-illustration: figure[role=img][aria-label] for drawn scenes; .mt-illustration-tag marks it (e.g. "Illustration").
|
|
10
|
+
.mt-illustration { position: relative; margin: 0 0 1.5rem; }
|
|
11
|
+
.mt-illustration-tag { position: absolute; inset-block-start: .5rem; inset-inline-start: .5rem; padding: .125rem .5rem; border: 1px solid mt(border); border-radius: 999px; background: mt(background); color: mt(foreground); font-size: .75rem; }
|
|
9
12
|
}
|
|
@@ -5,4 +5,7 @@
|
|
|
5
5
|
.mt-hero > p:first-of-type { font-size: 1.2rem; line-height: 1.6; color: mt(muted-foreground); max-width: 40rem; }
|
|
6
6
|
.mt-section { padding: mt(space-section) 0 0; }
|
|
7
7
|
.mt-section > h2:first-child { margin-top: 0; }
|
|
8
|
+
// decor: an aria-hidden ornament in the top end corner; it never takes clicks.
|
|
9
|
+
.mt-has-decor { position: relative; }
|
|
10
|
+
.mt-section-decor { position: absolute; inset-block-start: 0; inset-inline-end: 0; pointer-events: none; }
|
|
8
11
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Scroll reveal: .mt-reveal (reveal: true on a section or hero:). CSS only, no script.
|
|
2
|
+
// It runs only where scroll-driven animations exist and the reader allows motion; otherwise content is shown as is.
|
|
3
|
+
@include mt-layer(components) {
|
|
4
|
+
@supports (animation-timeline: view()) {
|
|
5
|
+
@media screen and (prefers-reduced-motion: no-preference) {
|
|
6
|
+
@keyframes mt-reveal { from { opacity: 0; translate: 0 1.5rem; } to { opacity: 1; translate: none; } }
|
|
7
|
+
.mt-reveal { animation: mt-reveal linear both; animation-timeline: view(); animation-range: entry 0% entry 60%; }
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Optional list styles (lists sheet): linked only by pages with .mt-hero-checks, ul.mt-chips or .mt-item-title.
|
|
2
|
+
// .mt-hero-checks: the hero's first ul is a row of ✓ chips in --mt-ok (default: the status-available colour; a site may set its own). ul.mt-chips: link-only items as 44px chips with →.
|
|
3
|
+
// .mt-item-title: **Title**: items get a bold title and a muted separator.
|
|
4
|
+
@include mt-layer(components) {
|
|
5
|
+
:where(:root) { --mt-ok: #{mt(status-available)}; }
|
|
6
|
+
.mt-hero-checks > ul:first-of-type, ul.mt-chips { display: flex; flex-wrap: wrap; gap: .5rem; padding: 0; list-style: none; }
|
|
7
|
+
.mt-hero-checks > ul:first-of-type > li { display: inline-flex; align-items: center; gap: .375rem; margin: 0; padding: .25rem .75rem; border: 1px solid mt(border); border-radius: 999px; }
|
|
8
|
+
.mt-hero-checks > ul:first-of-type > li::before { content: "✓" / ""; color: var(--mt-ok); font-weight: 700; }
|
|
9
|
+
ul.mt-chips > li { margin: 0; }
|
|
10
|
+
ul.mt-chips a { display: inline-flex; align-items: center; gap: .375rem; min-height: 44px; padding: 0 1rem; border: 1px solid mt(border); border-radius: 999px; color: mt(foreground); text-decoration: none; }
|
|
11
|
+
ul.mt-chips a::after { content: "→" / ""; color: mt(muted-foreground); }
|
|
12
|
+
:dir(rtl) ul.mt-chips a::after, [dir="rtl"] ul.mt-chips a::after { content: "←" / ""; }
|
|
13
|
+
ul.mt-chips a:hover { border-color: mt(primary); }
|
|
14
|
+
.mt-item-title { font-weight: 700; }
|
|
15
|
+
.mt-item-sep { color: mt(muted-foreground); }
|
|
16
|
+
}
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
.mt-c-features > ul > li code { white-space: nowrap; }
|
|
9
9
|
.mt-c-features > ul > li:hover { border-color: color-mix(in srgb, #{mt(primary)} 40%, #{mt(border)}); box-shadow: mt(shadow); }
|
|
10
10
|
.mt-c-features > ul > li > strong:first-child { display: block; margin-bottom: .35rem; color: mt(card-foreground); font-size: 1rem; }
|
|
11
|
+
// badge: bottom: a status badge (.mt-badge) written as a direct child of the item sits at the card's bottom edge.
|
|
12
|
+
.mt-badge-bottom > ul > li:has(> .mt-badge) { position: relative; padding-block-end: calc(var(--mt-card-padding) + 2rem); }
|
|
13
|
+
.mt-badge-bottom > ul > li > .mt-badge { position: absolute; inset-block-end: var(--mt-card-padding); inset-inline-start: var(--mt-card-padding); }
|
|
11
14
|
@media (min-width: 48rem) {
|
|
12
15
|
.mt-cols-2 > ul { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
13
16
|
.mt-cols-3 > ul { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Split: c: split; text (.mt-section-body) and the visual: include (.mt-section-visual) side by side from 48rem,
|
|
2
|
+
// stacked below. Grid columns follow the writing direction, so start/end flip in RTL. DOM order stays text first.
|
|
3
|
+
@include mt-layer(components) {
|
|
4
|
+
.mt-section-in { display: grid; gap: 2rem; }
|
|
5
|
+
.mt-section-in > * { min-width: 0; }
|
|
6
|
+
.mt-section-body > :last-child, .mt-section-visual > :last-child { margin-bottom: 0; }
|
|
7
|
+
.mt-section-visual img, .mt-section-visual svg { display: block; max-width: 100%; height: auto; }
|
|
8
|
+
@media (min-width: 48rem) {
|
|
9
|
+
.mt-c-split > .mt-section-in { grid-template-columns: var(--mt-split-body, 1fr) var(--mt-split-visual, 1fr); align-items: center; }
|
|
10
|
+
.mt-split-5-7 { --mt-split-body: 5fr; --mt-split-visual: 7fr; }
|
|
11
|
+
.mt-split-start > .mt-section-in { grid-template-columns: var(--mt-split-visual, 1fr) var(--mt-split-body, 1fr); }
|
|
12
|
+
.mt-split-start .mt-section-visual { grid-row: 1; grid-column: 1; }
|
|
13
|
+
}
|
|
14
|
+
}
|
data/_sass/modootoday.scss
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
@import "modootoday/components/core/inline/figure";
|
|
8
8
|
@import "modootoday/components/core/inline/code-copy";
|
|
9
9
|
@import "modootoday/components/core/inline/hero";
|
|
10
|
+
@import "modootoday/components/core/inline/reveal";
|
|
10
11
|
@import "modootoday/components/core/inline/cta";
|
|
11
12
|
@import "modootoday/components/section/showcase/cta";
|
|
12
13
|
@import "modootoday/components/core/inline/code";
|
|
@@ -37,4 +38,5 @@
|
|
|
37
38
|
@import "modootoday/components/section/structure/details";
|
|
38
39
|
@import "modootoday/components/section/structure/faq";
|
|
39
40
|
@import "modootoday/components/section/structure/params";
|
|
41
|
+
@import "modootoday/components/section/structure/split";
|
|
40
42
|
@import "modootoday/access";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
# md-components v1 — jekyll-theme-modootoday optional sheet (hero check row, link chips, titled items). Linked only by pages that use it.
|
|
3
|
+
---
|
|
4
|
+
{%- include modootoday/config.html -%}
|
|
5
|
+
$mt-css-layers: {{ mt_css_layers }};
|
|
6
|
+
@import "modootoday/sheet";
|
|
7
|
+
{% if mt_components contains "lists" %}@import "modootoday/components/lists/lists";
|
|
8
|
+
{% endif %}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
# md-components v1 — jekyll-theme-modootoday section sheet (c: split). Linked only by pages that use it.
|
|
3
|
+
---
|
|
4
|
+
{%- include modootoday/config.html -%}
|
|
5
|
+
$mt-css-layers: {{ mt_css_layers }};
|
|
6
|
+
@import "modootoday/sheet";
|
|
7
|
+
@import "modootoday/components/section/structure/split";
|
data/i18n/glossary.yml
CHANGED
|
@@ -6,7 +6,10 @@ register:
|
|
|
6
6
|
ko: {docs: 합니다체, ui: 해요체, labels: noun phrase}
|
|
7
7
|
ja: {docs: です・ます, ui: です・ます, labels: 体言止め, table_cells: 体言止め or 常体}
|
|
8
8
|
# Pages whose front matter has `noindex: true` are sample content (demo posts) and keep their genre voice.
|
|
9
|
+
# Brand: the theme's visible name always carries the word for theme (the plain name is a separate service).
|
|
10
|
+
# Gem, repository and code names (jekyll-theme-modootoday, modootoday-check) are not translated.
|
|
9
11
|
terms:
|
|
12
|
+
- {en: modoo.today theme (brand name), ko: 모두의오늘 테마, ja: modoo.today テーマ}
|
|
10
13
|
- {en: Markdown twin, ko: Markdown 버전, ja: Markdown 版, avoid: {ko: [쌍둥이, 트윈], ja: [ツイン, 双子]}}
|
|
11
14
|
- {en: front matter, ko: front matter, ja: front matter, avoid: {ko: [머리말, 프런트 매터, 프론트 매터], ja: [フロントマター]}}
|
|
12
15
|
- {en: breadcrumb, ko: 이동 경로, ja: パンくずリスト, avoid: {ko: [브레드크럼, 빵 부스러기], ja: [ブレッドクラム]}}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Modootoday
|
|
4
|
+
module Check
|
|
5
|
+
# .mt-illustration (WCAG 1.1.1): a drawn scene is one image to assistive technology, so it must be
|
|
6
|
+
# <figure role="img"> with a non-empty aria-label; its children (and any .mt-illustration-tag) are not read.
|
|
7
|
+
module Illustration
|
|
8
|
+
OPEN = /<([a-z][a-z0-9]*)\b[^>]*\bclass="[^"]*\bmt-illustration\b(?!-)[^"]*"[^>]*>/i
|
|
9
|
+
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def call(ctx)
|
|
13
|
+
Dir.glob("#{ctx.site}/**/*.html").each do |f|
|
|
14
|
+
File.read(f).gsub(%r{<pre\b.*?</pre>}m, "").scan(OPEN) do
|
|
15
|
+
tag, el = Regexp.last_match(1), Regexp.last_match(0)
|
|
16
|
+
label = el[/\baria-label="([^"]*)"/, 1].to_s.strip
|
|
17
|
+
next if tag.casecmp?("figure") && el =~ /\brole="img"/ && !label.empty?
|
|
18
|
+
ctx.errs << "#{f}: .mt-illustration must be <figure role=\"img\" aria-label=\"…\"> with a non-empty label (got #{el[0, 120]})"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/modootoday/check/cli.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Modootoday
|
|
|
4
4
|
module Check
|
|
5
5
|
# Command line: usage, --help/--version, running the rule groups in order, reporting.
|
|
6
6
|
module CLI
|
|
7
|
-
USAGE = "usage: modootoday-check SRC SITE [--twins] [--github-pages[=VERSION]] [--gh] [--strict] [--schema-recommended] [--i18n] [--i18n-init=LANG,...]"
|
|
7
|
+
USAGE = "usage: modootoday-check SRC SITE [--twins] [--github-pages[=VERSION]] [--gh] [--strict] [--schema-recommended] [--i18n] [--i18n-pages] [--i18n-init=LANG,...]"
|
|
8
8
|
# Single source for --help and the README "Commands" table (script/readme-commands, test/project/readme_test.rb).
|
|
9
9
|
OPTIONS = [
|
|
10
10
|
["SRC SITE", "always: front matter, forbidden syntax, alerts, fence info strings, `status:`/`tag:`/`kbd:` values (`since:` is rejected), `sections:` count, `_data/i18n/<lang>.yml` keys against the default language and translated pages against default-language pages, `_data/components.yml` (keys, slot contract counts per section, `parts` against `api.md` and the built HTML), Sass/CSS rules, unconverted markers in the build, schema.org JSON-LD in the build (valid JSON, vocabulary, required properties per type, absolute URLs, ISO 8601 dates, one graph per page, agreement with Open Graph)"],
|
|
@@ -13,6 +13,7 @@ module Modootoday
|
|
|
13
13
|
["--schema-recommended", "also warn about schema.org properties Google Search recommends (author, image, dates, ...) that a JSON-LD node lacks"],
|
|
14
14
|
["--strict", "warnings fail the run"],
|
|
15
15
|
["--i18n", "`_data/i18n/<lang>.yml` against the theme registry (`i18n/en.yml` in the gem): unknown keys, `%{name}` placeholder mismatches, and pages marked `translation: pending`"],
|
|
16
|
+
["--i18n-pages", "warn about default-language pages with no translation in a `modootoday.full_languages` language (the page with the same `ref:`, else the same path under `<lang>/`); with `--strict` they fail"],
|
|
16
17
|
["--i18n-init=LANG,...", "copy the theme's catalogs (`i18n/<lang>.yml`, 23 languages) into `SRC/_data/i18n/` as a starting point for overrides (optional; the theme already uses them), and list keys an existing catalog lacks"],
|
|
17
18
|
["--gh", "also render each page with `gh api markdown` (network, `gh` login)"],
|
|
18
19
|
["--help, -h", "print usage and options (`--help=markdown` prints the README table)"],
|
|
@@ -20,7 +21,7 @@ module Modootoday
|
|
|
20
21
|
].freeze
|
|
21
22
|
# Rule groups in report order.
|
|
22
23
|
RULES = [Registry, SiteConfig.method(:source_mode), Pages, Layouts, I18n, Registry.method(:i18n_keys), BuiltParts,
|
|
23
|
-
BuildOutput.method(:residue), NewWindow.method(:built), StructuredData, Stylesheets, BuildOutput.method(:css), SiteConfig, Renderers, Blog, GithubPages, Twins, GhRender].freeze
|
|
24
|
+
BuildOutput.method(:residue), NewWindow.method(:built), Illustration, StructuredData, Stylesheets, BuildOutput.method(:css), SiteConfig, Renderers, Blog, GithubPages, Twins, GhRender].freeze
|
|
24
25
|
|
|
25
26
|
module_function
|
|
26
27
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Modootoday
|
|
4
4
|
module Check
|
|
5
5
|
# Values the transforms need (Rule 2b): inline `file:`, `progress:`, `embed:` code spans, and per-section
|
|
6
|
-
# content rules for c: gallery, quote, pricing and subscribe that slot counts cannot express.
|
|
6
|
+
# content rules for c: gallery, quote, pricing, split and subscribe that slot counts cannot express.
|
|
7
7
|
module ComponentRules
|
|
8
8
|
SKELETONS = %w[text card image avatar row].freeze
|
|
9
9
|
|
|
@@ -43,6 +43,8 @@ module Modootoday
|
|
|
43
43
|
n = m.scan(/^###(?: |$)/).size
|
|
44
44
|
rec = s["recommended"]
|
|
45
45
|
errs << "#{w}: recommended: must be a plan number from 1 to #{n}" if s.key?("recommended") && !(rec.is_a?(Integer) && rec.between?(1, n))
|
|
46
|
+
when "split"
|
|
47
|
+
errs << "#{w}: needs visual: <name> (the _includes/sections/<name>.html shown beside the text)" unless s["visual"].is_a?(String) && !s["visual"].strip.empty?
|
|
46
48
|
when "subscribe"
|
|
47
49
|
act = ctx.mtc.is_a?(Hash) && ctx.mtc.dig("subscribe", "action")
|
|
48
50
|
ctx.warns << "#{w}: no form is shown until _config.yml sets modootoday.subscribe.action" unless act
|
|
@@ -32,6 +32,49 @@ module Modootoday
|
|
|
32
32
|
init(ctx) if ctx.argv.any? { |a| a.start_with?("--i18n-init") }
|
|
33
33
|
follow_default(ctx)
|
|
34
34
|
registry(ctx) if ctx.option?("--i18n") && File.exist?("#{THEME}/en.yml")
|
|
35
|
+
refs(ctx)
|
|
36
|
+
pages(ctx) if ctx.option?("--i18n-pages")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Each page as [rel path, front matter, language]: lang: from front matter, else the /<lang>/ folder
|
|
40
|
+
# when that code is in modootoday.languages, else the default language (site lang).
|
|
41
|
+
def page_index(ctx)
|
|
42
|
+
langs = Array(ctx.mtc["languages"]).map(&:to_s)
|
|
43
|
+
default = ctx.site_cfg["lang"].to_s.empty? ? "en" : ctx.site_cfg["lang"].to_s
|
|
44
|
+
ctx.mds.map do |f|
|
|
45
|
+
r = ctx.rel(f)
|
|
46
|
+
fm = (Markdown.fm(File.read(f)) rescue {}) || {}
|
|
47
|
+
dir = r.split("/").first
|
|
48
|
+
[r, fm, (fm["lang"] || (langs.include?(dir) && r.include?("/") ? dir : default)).to_s]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# {% include modootoday/link.html ref="x" %} needs a page with front matter ref: x.
|
|
53
|
+
def refs(ctx)
|
|
54
|
+
files = (ctx.mds + Dir.glob("#{ctx.src}/{_includes,_layouts}/**/*.html")).reject { |f| f.include?("/_site/") }
|
|
55
|
+
uses = files.flat_map { |f| Markdown.strip_fences(File.read(f)).gsub(/`[^`\n]*`/, "").scan(/\{%-?\s*include\s+modootoday\/link\.html\b[^%]*\bref=["']([^"']+)["']/).flatten.map { |x| [ctx.rel(f), x] } }
|
|
56
|
+
return if uses.empty?
|
|
57
|
+
known = page_index(ctx).map { |_, fm, _| fm["ref"].to_s }.reject(&:empty?)
|
|
58
|
+
uses.each { |r, x| ctx.errs << "#{r}: link.html ref=\"#{x}\": no page has front matter ref: #{x}" unless known.include?(x) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# --i18n-pages: every default-language page has a translation in each modootoday.full_languages language
|
|
62
|
+
# (the page with the same ref:, or without ref: the same path under <lang>/). Warnings; --strict fails.
|
|
63
|
+
def pages(ctx)
|
|
64
|
+
full = Array(ctx.mtc["full_languages"]).map(&:to_s)
|
|
65
|
+
default = ctx.site_cfg["lang"].to_s.empty? ? "en" : ctx.site_cfg["lang"].to_s
|
|
66
|
+
return ctx.warns << "--i18n-pages: set modootoday.full_languages to the languages that translate every page" if full.empty?
|
|
67
|
+
idx = page_index(ctx)
|
|
68
|
+
have = idx.to_h { |r, fm, l| [[l, fm["ref"] ? "ref:#{fm['ref']}" : r], true] }
|
|
69
|
+
idx.each do |r, fm, l|
|
|
70
|
+
next unless l == default && fm["layout"] != "twin"
|
|
71
|
+
full.each do |fl|
|
|
72
|
+
next if fl == default
|
|
73
|
+
key = fm["ref"] ? "ref:#{fm['ref']}" : "#{fl}/#{r}"
|
|
74
|
+
next if have[[fl, key]]
|
|
75
|
+
ctx.warns << "#{r}: no #{fl} page (#{fm['ref'] ? "ref: #{fm['ref']}" : "#{fl}/#{r}"}); #{fl} is in modootoday.full_languages"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
35
78
|
end
|
|
36
79
|
|
|
37
80
|
def init(ctx)
|
|
@@ -22,18 +22,23 @@ module Modootoday
|
|
|
22
22
|
components(ctx, r, secs, sec_md) if ctx.comps
|
|
23
23
|
hero = meta["hero"]
|
|
24
24
|
errs << "#{r}: hero: must be a map such as {visual: name}" if hero && !hero.is_a?(Hash)
|
|
25
|
+
errs << "#{r}: hero.checks must be true or false" if hero.is_a?(Hash) && hero.key?("checks") && ![true, false].include?(hero["checks"])
|
|
25
26
|
visuals(ctx, r, secs, hero.is_a?(Hash) ? hero : nil)
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
# visual: <name> on a section item or on hero: needs _includes/sections/<name>.html in the site or the theme (showcase).
|
|
29
|
+
# reveal: is a boolean. visual: <name> and decor: <name> on a section item or on hero: needs _includes/sections/<name>.html in the site or the theme (showcase).
|
|
29
30
|
def visuals(ctx, r, secs, hero)
|
|
30
31
|
items = secs.each_with_index.map { |s, i| [s, "sections[#{i}]"] }
|
|
31
32
|
items << [hero, "hero"] if hero
|
|
32
33
|
items.each do |s, where|
|
|
33
|
-
next unless s.is_a?(Hash)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
next unless s.is_a?(Hash)
|
|
35
|
+
ctx.errs << "#{r}: #{where}.reveal must be true or false" if s.key?("reveal") && ![true, false].include?(s["reveal"])
|
|
36
|
+
%w[visual decor].each do |key|
|
|
37
|
+
next unless s.key?(key)
|
|
38
|
+
v = s[key].to_s
|
|
39
|
+
next ctx.errs << "#{r}: #{where}.#{key} must be an include name [a-z0-9_-] (got #{s[key].inspect})" unless v =~ /\A[a-z0-9][a-z0-9_-]*\z/
|
|
40
|
+
ctx.errs << "#{r}: #{where}.#{key}: _includes/sections/#{v}.html not found" unless [ctx.src, THEME].any? { |d| File.exist?(File.join(d, "_includes/sections/#{v}.html")) }
|
|
41
|
+
end
|
|
37
42
|
end
|
|
38
43
|
end
|
|
39
44
|
|
|
@@ -57,7 +62,9 @@ module Modootoday
|
|
|
57
62
|
params = spec["params"] || {}
|
|
58
63
|
Slots.check_section(errs, r, i, s["c"], spec["slots"], sec_md[i])
|
|
59
64
|
(ctx.part_uses[s["c"]] ||= []) << r if spec.is_a?(Hash) && spec["parts"].is_a?(Array)
|
|
60
|
-
(s.keys - %w[c name visual]).each do |k|
|
|
65
|
+
(s.keys - %w[c name visual decor reveal]).each do |k|
|
|
66
|
+
# with visual:, other keys are the visual include's own params (include.section.<key>)
|
|
67
|
+
next if !params.key?(k) && s.key?("visual")
|
|
61
68
|
next errs << "#{r}: sections[#{i}] #{s['c']}: unknown param '#{k}'" unless params.key?(k)
|
|
62
69
|
allowed = params[k].is_a?(Hash) && params[k]["allowed"]
|
|
63
70
|
errs << "#{r}: sections[#{i}] #{s['c']}.#{k}=#{s[k].inspect} not in #{allowed.inspect}" if allowed && !allowed.include?(s[k])
|
|
@@ -52,13 +52,16 @@ module Modootoday
|
|
|
52
52
|
|
|
53
53
|
# Tool-generated region markers on their own line, e.g. <!-- spec:toc:begin --> / <!-- spec:toc:end -->
|
|
54
54
|
MARKER = /^[ \t]*<!--[ \t]*[a-z][a-z0-9-]*(?::[a-z0-9._-]+)*:(?:begin|end)[ \t]*-->[ \t]*$/
|
|
55
|
-
# specfold generated values, own-line or inline, one line each: <!-- spec:count -->12<!-- /spec:count
|
|
56
|
-
|
|
55
|
+
# specfold generated values, own-line or inline, one line each: <!-- spec:count -->12<!-- /spec:count -->.
|
|
56
|
+
# Arguments may follow the name after a space (<!-- spec:count rows="All commands" -->) up to the closing -->;
|
|
57
|
+
# they stay on one line and contain no `>`, `--` or `##` (also inside quotes).
|
|
58
|
+
SPEC = %r{<!--[ \t]*/?spec:[a-z0-9._-]+(?::[a-z0-9._-]+)*(?:[ \t]+(?:(?!--|\#\#)[^>\n])*)?-->}
|
|
57
59
|
|
|
58
60
|
# 1c. forbidden syntax outside code
|
|
59
61
|
def forbidden(ctx, f, code, html_free)
|
|
60
62
|
r = ctx.rel(f)
|
|
61
|
-
|
|
63
|
+
left = code.gsub(MARKER, "").gsub(SPEC, "")[/<!--[^\n]{0,60}/]
|
|
64
|
+
ctx.errs << "#{r}: HTML comment <!-- --> (hidden on GitHub, emitted by kramdown); remove it (first: `#{left.strip}`)" if left
|
|
62
65
|
html_free.each_line.with_index(1) do |l, n|
|
|
63
66
|
linkless = l.gsub(/\]\([^)]*\)/, "]()").gsub(/<(https?:|mailto:)[^>]*>|<[^@\s>]+@[^>\s]+>/, "<>").sub(/^ {0,3}\[[^\]]+\]:\s*\S+/, "")
|
|
64
67
|
why = case l
|
|
@@ -4,7 +4,7 @@ module Modootoday
|
|
|
4
4
|
module Check
|
|
5
5
|
# The modootoday: settings in the site's _config.yml.
|
|
6
6
|
module SiteConfig
|
|
7
|
-
COMPONENTS = %w[callout badge hero cta card tabs code-copy nav sidebar page-actions pagination theme-toggle breadcrumb toc accordion steps figure timeline kbd search code footnotes progress embed banner filetree details faq params linkcards quote gallery pricing subscribe loading].freeze
|
|
7
|
+
COMPONENTS = %w[callout badge hero cta card tabs code-copy nav sidebar page-actions pagination theme-toggle breadcrumb toc accordion steps figure timeline kbd search code footnotes progress embed banner filetree details faq params linkcards quote gallery pricing subscribe split loading lists reveal].freeze
|
|
8
8
|
SEMANTIC = %w[background foreground muted muted-foreground card card-foreground primary primary-foreground brand accent
|
|
9
9
|
accent-foreground border ring note tip important warning caution status-available status-partial
|
|
10
10
|
status-planned font-sans font-mono font-size line-height measure space radius].freeze
|
|
@@ -25,6 +25,12 @@ module Modootoday
|
|
|
25
25
|
return errs << "_config.yml: modootoday: must be a map" if mtc && !mtc.is_a?(Hash)
|
|
26
26
|
return unless mtc.is_a?(Hash)
|
|
27
27
|
enums(mtc, errs)
|
|
28
|
+
full_languages(mtc, errs)
|
|
29
|
+
if mtc.key?("lists")
|
|
30
|
+
l = mtc["lists"]
|
|
31
|
+
ok = l.is_a?(Hash) && (l.keys - %w[link_chips titled_items]).empty? && l.values.all? { |v| [true, false].include?(v) }
|
|
32
|
+
errs << "_config.yml: modootoday.lists must be a map of link_chips and titled_items set to true or false" unless ok
|
|
33
|
+
end
|
|
28
34
|
if mtc.key?("archive")
|
|
29
35
|
a = mtc["archive"]
|
|
30
36
|
if !a.is_a?(Hash) || !(a.keys - %w[tags categories]).empty?
|
|
@@ -53,6 +59,14 @@ module Modootoday
|
|
|
53
59
|
errs << "_config.yml: modootoday.languages must be a list of language codes such as [en, ko]" if mtc.key?("languages") && !(mtc["languages"].is_a?(Array) && mtc["languages"].all? { |l| l.to_s =~ /\A[a-z]{2,3}(-[A-Za-z0-9]+)*\z/ })
|
|
54
60
|
end
|
|
55
61
|
|
|
62
|
+
# full_languages: the languages that must translate every default-language page (modootoday-check --i18n-pages).
|
|
63
|
+
def full_languages(mtc, errs)
|
|
64
|
+
return unless mtc.key?("full_languages")
|
|
65
|
+
fl, langs = mtc["full_languages"], Array(mtc["languages"]).map(&:to_s)
|
|
66
|
+
return errs << "_config.yml: modootoday.full_languages must be a list of codes from modootoday.languages" unless fl.is_a?(Array)
|
|
67
|
+
(fl.map(&:to_s) - langs).each { |l| errs << "_config.yml: modootoday.full_languages: '#{l}' is not in modootoday.languages" }
|
|
68
|
+
end
|
|
69
|
+
|
|
56
70
|
def tokens(ctx)
|
|
57
71
|
mtc, errs = ctx.mtc, ctx.errs
|
|
58
72
|
%w[tokens tokens_dark].each do |k|
|
|
@@ -12,6 +12,10 @@ module Modootoday
|
|
|
12
12
|
module StructuredData
|
|
13
13
|
BLOCK = %r{<script type="application/ld\+json">(.*?)</script>}m
|
|
14
14
|
CONTEXT = %r{\Ahttps?://schema\.org/?\z}
|
|
15
|
+
# jekyll-seo-tag output (sites with seo: false that bring the plugin). Its JSON-LD is third-party markup the kit
|
|
16
|
+
# does not write: it is checked only for valid JSON and noted as a warning, not held to the kit's rules
|
|
17
|
+
# (for example WebPage with headline but no name). schema.org itself marks no property as required.
|
|
18
|
+
SEO_TAG = /<!-- Begin Jekyll SEO tag.*?<!-- End Jekyll SEO tag -->/m
|
|
15
19
|
|
|
16
20
|
module_function
|
|
17
21
|
|
|
@@ -20,6 +24,15 @@ module Modootoday
|
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
def page(ctx, f, html)
|
|
27
|
+
html.scan(SEO_TAG).each do |seo|
|
|
28
|
+
seo.scan(BLOCK).flatten.each do |b|
|
|
29
|
+
JSON.parse(b)
|
|
30
|
+
ctx.warns << "#{f}: JSON-LD from jekyll-seo-tag not checked against the kit's schema rules (third-party markup)"
|
|
31
|
+
rescue JSON::ParserError => e
|
|
32
|
+
ctx.errs << "#{f}: jekyll-seo-tag JSON-LD is not valid JSON (#{e.message[0, 80]})"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
html = html.gsub(SEO_TAG, "")
|
|
23
36
|
blocks = html.scan(BLOCK).flatten
|
|
24
37
|
return if blocks.empty?
|
|
25
38
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-theme-modootoday
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- modootoday
|
|
@@ -129,6 +129,7 @@ files:
|
|
|
129
129
|
- _includes/modootoday/markdown/c/subscribe.html
|
|
130
130
|
- _includes/modootoday/markdown/components.html
|
|
131
131
|
- _includes/modootoday/markdown/inline.html
|
|
132
|
+
- _includes/modootoday/markdown/lists.html
|
|
132
133
|
- _includes/modootoday/markdown/llms-pages.html
|
|
133
134
|
- _includes/modootoday/markdown/raw-body.html
|
|
134
135
|
- _includes/modootoday/markdown/sections.html
|
|
@@ -148,6 +149,7 @@ files:
|
|
|
148
149
|
- _includes/modootoday/pages/hero/scene.html
|
|
149
150
|
- _includes/modootoday/pages/hero/sparks.html
|
|
150
151
|
- _includes/modootoday/pages/search-form.html
|
|
152
|
+
- _includes/modootoday/ref-url.html
|
|
151
153
|
- _includes/modootoday/render/asset.html
|
|
152
154
|
- _includes/modootoday/render/math.html
|
|
153
155
|
- _includes/modootoday/render/mermaid.html
|
|
@@ -236,10 +238,12 @@ files:
|
|
|
236
238
|
- _sass/modootoday/components/core/inline/_hero.scss
|
|
237
239
|
- _sass/modootoday/components/core/inline/_kbd.scss
|
|
238
240
|
- _sass/modootoday/components/core/inline/_progress.scss
|
|
241
|
+
- _sass/modootoday/components/core/inline/_reveal.scss
|
|
239
242
|
- _sass/modootoday/components/doc/_page-actions.scss
|
|
240
243
|
- _sass/modootoday/components/doc/_sidebar.scss
|
|
241
244
|
- _sass/modootoday/components/doc/_toc.scss
|
|
242
245
|
- _sass/modootoday/components/figure/_figure-svg.scss
|
|
246
|
+
- _sass/modootoday/components/lists/_lists.scss
|
|
243
247
|
- _sass/modootoday/components/loading/_loading.scss
|
|
244
248
|
- _sass/modootoday/components/search/_search.scss
|
|
245
249
|
- _sass/modootoday/components/section/showcase/_card.scss
|
|
@@ -254,6 +258,7 @@ files:
|
|
|
254
258
|
- _sass/modootoday/components/section/structure/_faq.scss
|
|
255
259
|
- _sass/modootoday/components/section/structure/_filetree.scss
|
|
256
260
|
- _sass/modootoday/components/section/structure/_params.scss
|
|
261
|
+
- _sass/modootoday/components/section/structure/_split.scss
|
|
257
262
|
- _sass/modootoday/components/section/structure/_steps.scss
|
|
258
263
|
- _sass/modootoday/components/section/structure/_tabs.scss
|
|
259
264
|
- _sass/modootoday/components/section/structure/_timeline.scss
|
|
@@ -301,6 +306,7 @@ files:
|
|
|
301
306
|
- assets/css/modootoday.scss
|
|
302
307
|
- assets/css/modootoday/doc.scss
|
|
303
308
|
- assets/css/modootoday/figure.scss
|
|
309
|
+
- assets/css/modootoday/lists.scss
|
|
304
310
|
- assets/css/modootoday/loading.scss
|
|
305
311
|
- assets/css/modootoday/search.scss
|
|
306
312
|
- assets/css/modootoday/showcase/card.scss
|
|
@@ -315,6 +321,7 @@ files:
|
|
|
315
321
|
- assets/css/modootoday/structure/faq.scss
|
|
316
322
|
- assets/css/modootoday/structure/filetree.scss
|
|
317
323
|
- assets/css/modootoday/structure/params.scss
|
|
324
|
+
- assets/css/modootoday/structure/split.scss
|
|
318
325
|
- assets/css/modootoday/structure/steps.scss
|
|
319
326
|
- assets/css/modootoday/structure/tabs.scss
|
|
320
327
|
- assets/css/modootoday/structure/timeline.scss
|
|
@@ -365,6 +372,7 @@ files:
|
|
|
365
372
|
- lib/jekyll-theme-modootoday.rb
|
|
366
373
|
- lib/modootoday/check.rb
|
|
367
374
|
- lib/modootoday/check/a11y/content.rb
|
|
375
|
+
- lib/modootoday/check/a11y/illustration.rb
|
|
368
376
|
- lib/modootoday/check/a11y/new_window.rb
|
|
369
377
|
- lib/modootoday/check/blog.rb
|
|
370
378
|
- lib/modootoday/check/build_output.rb
|