yass 0.6.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18181b3e885b9090e2762e55e71daa470ccca3412a5443e420294801aee2df19
4
- data.tar.gz: 64a1a13fe168ab5b06993275d2a6e401a93f7870af4958c3651b2b6ca5c4c46f
3
+ metadata.gz: 649645d7b796ba02544a816464ff18efb5fdac5c3e914f16ce39ebde71337a37
4
+ data.tar.gz: e6e2268d8733f20efb0f03f7b29c2a5a58e8e0deac5a0a4d796db3ca2ae78971
5
5
  SHA512:
6
- metadata.gz: b78a2210e4cd074f360bb6313526dd7a99fb2113cb28c5f540631e91aed3ec3a6fba7702665d430542c4184e142a281dd4321ec84064eb9faae16eee20d229c6
7
- data.tar.gz: eeb68ad56783c4c7c545e446dca271a023c71756955d3b9f017afc034131a3b02c19fc858b06ae739c0e947b015279001dfc6dd617d57565db512e71a04eaffa
6
+ metadata.gz: e0eae7b97dbf4cc49a7e37812f867d0734e249058f560e58067be91d69abd4c2ce3e3a4e37eb5203555bc2135fc958a7c30c80cac67e1cd6c0551e44548c0c10
7
+ data.tar.gz: df0d5bf462455417fed28d9725fee69bba326284e20e57532fb6a27a142363e8c91d4f670735f71d72a82a670dd2ec1a67d468829d043ef82304f336701b2690
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jordan Hollinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -6,16 +6,21 @@ Yass is an incredibly un-opinionated static site generator. [Learn more!](https:
6
6
 
7
7
  ## Getting started
8
8
 
9
- Starting from an empty page isn't fun, so `yass init` will create a skeleton site for you.
9
+ Starting from a blank page isn't fun, so `yass init` spits out the source to [jhollinger.github.io/yass/](https://jhollinger.github.io/yass/) to help get you started.
10
10
 
11
11
  ```bash
12
12
  $ gem install yass
13
13
  $ yass init blog
14
14
  Creating blog/layouts/default.html.liquid
15
- Creating blog/site/assets/highlight.min.css
15
+ Creating blog/layouts/splash.html.liquid
16
16
  Creating blog/site/assets/highlight.min.js
17
- Creating blog/site/index.html.liquid
17
+ Creating blog/site/assets/highlightjs-atom-one-dark.min.css
18
+ Creating blog/site/assets/main.css.liquid
19
+ Creating blog/site/helpers/index.md.liquid
20
+ Creating blog/site/index.md.liquid
21
+ Creating blog/site/layouts-templates/index.md.liquid
18
22
  Creating blog/templates/asset_tags.liquid
23
+ Creating blog/templates/nav.liquid
19
24
  $ cd blog
20
25
  ```
21
26
 
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>{{ page.title }}</title>
7
+ <link rel="icon" href="{{ "favicon.png" | relative }}" sizes="32x32">
8
+ {% render "asset_tags", files: files, page: page %}
9
+ </head>
10
+ <body>
11
+ <div id="wrapper">
12
+ <header>
13
+ <h1><a href="{{ "index.html" | relative | strip_index }}">Yass</a></h1>
14
+
15
+ {% render "nav", page: page %}
16
+ </header>
17
+
18
+ <section id="main" class="flex">
19
+ <div class="flex"></div>
20
+ <div class="content">
21
+ {{ content }}
22
+ </div>
23
+ <div class="flex"></div>
24
+ </section>
25
+ </div>
26
+
27
+ <footer></footer>
28
+ <script>hljs.highlightAll()</script>
29
+ </body>
30
+ </html>
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>{{ page.title }}</title>
7
+ <link rel="icon" href="{{ "favicon.png" | relative }}" sizes="32x32">
8
+ {% render "asset_tags", files: files, page: page %}
9
+ </head>
10
+ <body>
11
+ <div id="wrapper">
12
+ <header>
13
+ <div></div>
14
+ {% render "nav", page: page %}
15
+ </header>
16
+
17
+ <section id="hero">
18
+ <div class="flex"></div>
19
+ <div>
20
+ <div id="title">Yass</div>
21
+ <div id="subtitle">
22
+ <p>Yet Another Static Site (generator)</p>
23
+ </div>
24
+ </div>
25
+ <div class="flex"></div>
26
+ </section>
27
+
28
+ <section id="main" class="flex">
29
+ <div class="flex"></div>
30
+ <div class="content">
31
+ {{ content }}
32
+ </div>
33
+ <div class="flex"></div>
34
+ </section>
35
+
36
+ <footer></footer>
37
+ </div>
38
+ <script>hljs.highlightAll()</script>
39
+ </body>
40
+ </html>
@@ -0,0 +1 @@
1
+ pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
@@ -0,0 +1,156 @@
1
+ :root {
2
+ --purple: rgb(24, 10, 28);
3
+ --med-purple: rgb(54, 30, 78);
4
+ --med-purple: rgb(74, 50, 98);
5
+ --dark-grey: rgb(41, 44, 51);
6
+ --med-grey: rgb(87, 89, 93);
7
+ --light-grey: rgb(137, 139, 143);
8
+ --off-white: #d1d1d1;
9
+ --off-black: #222;
10
+ --bg-image: url("{{ 'assets/45-degree-fabric-dark.png' | relative }}");
11
+ }
12
+
13
+ @font-face {
14
+ font-family: "Kingthings Typewriter";
15
+ src: url("Kingthings-Typewriter.woff") format("woff");
16
+ }
17
+
18
+ @font-face {
19
+ font-family: "Comic Zine";
20
+ src: url("Comic-Zine.woff") format("woff");
21
+ }
22
+
23
+ * {
24
+ box-sizing: border-box;
25
+ padding: 0;
26
+ margin: 0;
27
+ }
28
+
29
+ body {
30
+ background-color: var(--dark-grey);
31
+ background-image: var(--bg-image);
32
+ color: var(--off-white);
33
+ }
34
+
35
+ header {
36
+ display: flex;
37
+ flex-direction: row;
38
+ justify-content: space-between;
39
+ align-items: center;
40
+ padding-left: 2rem;
41
+ }
42
+
43
+ header, #hero {
44
+ background-image: var(--bg-image);
45
+ background-color: var(--purple);
46
+ }
47
+
48
+ nav {
49
+ display: flex;
50
+ flex-direction: row;
51
+ flex-wrap: wrap;
52
+ justify-content: flex-end;
53
+ font-family: sans-serif;
54
+ }
55
+
56
+ nav > a:hover {
57
+ background-color: var(--off-white);
58
+ color: var(--purple);
59
+ box-shadow: inset 0px -8px 0px 0px var(--med-purple);
60
+ }
61
+
62
+ nav > a { padding: 1.5rem 2rem }
63
+ p { margin: 0.8rem 0 }
64
+ a {
65
+ color: var(--off-white);
66
+ text-decoration: none;
67
+ }
68
+ ul { margin: 1rem 0 1rem 1rem }
69
+
70
+ #wrapper {
71
+ display: flex;
72
+ flex-direction: column;
73
+ flex-wrap: nowrap;
74
+ width: 100vw;
75
+ min-height: 100vh;
76
+ }
77
+
78
+ #hero {
79
+ display: flex;
80
+ flex-direction: column;
81
+ padding: 3rem 0 6rem 0;
82
+ text-align: center;
83
+ }
84
+
85
+ #hero #title {
86
+ font-size: 10rem;
87
+ line-height: 9rem;
88
+ }
89
+
90
+ #hero #subtitle {
91
+ color: var(--light-grey);
92
+ font-size: 1.2rem;
93
+ }
94
+
95
+ #title, h1, h2, h3, h4, h5 { font-family: "Comic Zine", "Kingthings Typewriter", serif }
96
+ h1, h2, h3, h4, h5 { color: var(--purple) }
97
+ h1 { font-size: 3.0rem; margin: 1.5rem 0 0.5rem 0 }
98
+ h1:first-of-type { margin: 0 }
99
+ h2 { font-size: 2.25rem; margin: 1.5rem 0 0.5rem 0 }
100
+ h3 { font-size: 1.75rem; margin: 1.5rem 0 0.5rem 0 }
101
+ h4 { font-size: 1.5rem; margin: 1.5rem 0 0.5rem 0 }
102
+ h5 { font-size: 1.25rem; margin: 1.5rem 0 0.5rem 0 }
103
+
104
+ #main {
105
+ display: flex;
106
+ flex-direction: row;
107
+ }
108
+
109
+ .content {
110
+ width: 60%;
111
+ padding: 3rem 5rem;
112
+ background-color: var(--off-white);
113
+ color: var(--off-black);
114
+ }
115
+
116
+ .content a {
117
+ color: var(--purple);
118
+ text-decoration: underline;
119
+ }
120
+
121
+ a.button {
122
+ display: inline-block;
123
+ background-color: var(--med-purple);
124
+ background-image: var(--bg-image);
125
+ padding: 0.8rem;
126
+ border-radius: 3px;
127
+ color: var(--off-white);
128
+ text-decoration: none;
129
+ font-family: sans-serif;
130
+ font-size: 0.9rem;
131
+ white-space: nowrap;
132
+ }
133
+ a.button:hover { background-color: var(--med-purple) }
134
+
135
+ footer {
136
+ padding: 20px;
137
+ text-align: center;
138
+ }
139
+
140
+ code { border-radius: 3px }
141
+ code:not(.hljs) {
142
+ background-color: #bbb;
143
+ padding: 2px 4px;
144
+ }
145
+
146
+ .flex { flex: 1 1 auto }
147
+
148
+ @media (max-width: 500px) {
149
+ nav > a { padding: 1rem 0.75rem }
150
+ nav > a.home { display: none }
151
+ .content {
152
+ width: 100%;
153
+ padding: 1rem 1.5rem;
154
+ background-color: #f5f5f5;
155
+ }
156
+ }
Binary file
@@ -0,0 +1,96 @@
1
+ # Helpers
2
+
3
+ Your `.liquid` files have access to all the [standard Liquid tags and filters](https://shopify.github.io/liquid) plus the following ones from Yass.
4
+
5
+ ## Variables
6
+
7
+ ### page
8
+
9
+ An object representing the current page. Properties:
10
+
11
+ * `title` A titleized version of the filename (e.g. *My File* from *my-file.html*), or from YAML front matter
12
+ * `layout` Name of the page's layout (if any), e.g. *default.html*
13
+ * `src_path` Path with the original filename (e.g. *foo/bar/zorp.md.liquid*)
14
+ * `path` URL path relative to the relative root (e.g. *foo/bar/zorp.html*)
15
+ * `dirname` Directory file is in (e.g. *foo/bar* from *foo/bar/zorp.html*)
16
+ * `filename` Name of file (e.g. *zorp.html* from *foo/bar/zorp.html*)
17
+ * `extname` File extension (e.g. *.html* from *foo/bar/zorp.html*)
18
+ * `filesize` Size of file in bytes
19
+ * Any other value defined in the file's YAML front matter
20
+
21
+ {% highlight html %}
22
+ <h1>{% echo "{{" %} page.title {% echo "}}" %}</h1>
23
+ {% endhighlight %}
24
+
25
+ ### files
26
+
27
+ Any array of all files that will be written `dist/`. Same properties as `page`.
28
+
29
+ {% highlight html %}
30
+ {% echo '{% assign css_files = files | where: "extname", ".css" %' %}}
31
+ {% echo "{% for file in css_files %" %}}
32
+ <link rel="stylesheet" href="{% echo "{{ file.path | relative }}" %}">
33
+ {% echo "{% endfor %" %}}
34
+ {% endhighlight %}
35
+
36
+ ## Filters
37
+
38
+ ### relative
39
+
40
+ Modifies a path to be relative to the current file. Useful in layouts and template that need to refer to other files.
41
+
42
+ {% highlight html %}
43
+ <script src="{% echo "{{" %} "assets/main.js" | relative {% echo "}}" %}"></script>
44
+ {% endhighlight %}
45
+
46
+ If the above HTML was in `a/b/c.html.liquid`, the script source would be `../../assets/main.js`.
47
+
48
+ ### strip_index
49
+
50
+ Removes trailing `index.html`s from URLs, on the assumption that web servers will handle that. Can be disabled with the `--no-strip-index` option (useful for development builds).
51
+
52
+ {% highlight html %}
53
+ <a href="{% echo '{{ "posts/index.html" | relative | strip_index }}' %}">Posts</a>
54
+ {% endhighlight %}
55
+
56
+ ### match
57
+
58
+ Returns true if the string matches the regex.
59
+
60
+ {% highlight %}
61
+ {% echo '{% assign is_asset = page.path | match: "\.(css|js|jpe?g)$" %' %}}
62
+ {% endhighlight %}
63
+
64
+ ### where_match
65
+
66
+ Works like Liquid's built-it `where`, but accepts a regular expression.
67
+
68
+ {% highlight %}
69
+ {% echo '{% assign posts = where_match: "path", "^posts/.+\.html$" %' %}}
70
+ {% endhighlight %}
71
+
72
+ ## Tags
73
+
74
+ ### highlight
75
+
76
+ Converts the given code into something useable by [Highlight.js](https://highlightjs.org/).
77
+
78
+ {% highlight %}
79
+ {% echo "{%" %} highlight ruby {% echo "%" %}{% echo "}" %}
80
+ puts "Yass!"
81
+ {% echo "{%" %} endhighlight {% echo "%" %}{% echo "}" %}
82
+ {% endhighlight %}
83
+
84
+ Hightlight.js CSS and JS files with common languages are included by default with `yass init`. [Download](https://highlightjs.org/download) your own versions if you want different languages or themes.
85
+
86
+ ### render_content
87
+
88
+ Renders a template, passing the block as a variable named `content`.
89
+
90
+ The following will render the template `templates/my_template.liquid`:
91
+
92
+ {% highlight html %}
93
+ {% echo "{%" %} render_content "my_template" {% echo "%" %}{% echo "}" %}
94
+ <p>This will be rendered inside of "my_template" from a variable called "content"</p>
95
+ {% echo "{%" %} endrender_content {% echo "%" %}{% echo "}" %}
96
+ {% endhighlight %}
@@ -0,0 +1,60 @@
1
+ ---
2
+ layout: splash
3
+ ---
4
+ # What is Yass?
5
+
6
+ Yass is an astonishingly un-opinionated static site generator. Your sites's structure is entirely up to you: organize static assets, `.html` files, `.md` ([Markdown](https://commonmark.org/)) files, and `.liquid` ([Liquid](https://shopify.github.io/liquid/)) templates however you want under `site/`. Liquid layouts, reusable templates, and YAML front matter are supported.
7
+
8
+ The **one** opinion Yass holds is that **you** should decide everything. There's zero configuration and no conventions to learn!
9
+
10
+ ## Getting started
11
+
12
+ Starting from a blank page isn't fun, so `yass init` spits out the source to this very site to help get you started.
13
+
14
+ {% highlight bash %}
15
+ $ gem install yass
16
+ $ yass init blog
17
+ Creating blog/layouts/default.html.liquid
18
+ Creating blog/layouts/splash.html.liquid
19
+ Creating blog/site/assets/highlight.min.js
20
+ Creating blog/site/assets/highlightjs-atom-one-dark.min.css
21
+ Creating blog/site/assets/main.css.liquid
22
+ Creating blog/site/helpers/index.md.liquid
23
+ Creating blog/site/index.md.liquid
24
+ Creating blog/site/layouts-templates/index.md.liquid
25
+ Creating blog/templates/asset_tags.liquid
26
+ Creating blog/templates/nav.liquid
27
+ $ cd blog
28
+ {% endhighlight %}
29
+
30
+ * `site/` contains your site's source.
31
+ * `layouts/` contains [Liquid](https://shopify.github.io/liquid/) layouts (optional).
32
+ * `templates/` contains reusable [Liquid](https://shopify.github.io/liquid/) templates (optional).
33
+
34
+ ## Building
35
+
36
+ Build your site into the `dist/` directory with `yass build`.
37
+
38
+ {% highlight bash %}
39
+ $ yass build
40
+ {% endhighlight %}
41
+
42
+ ## Previewing
43
+
44
+ To preview your site on your computer, simply open `dist/index.html` with your browser 🤯. (This requires using relative links, but there are helpers for that.)
45
+
46
+ If you're building for webserverless, local viewing, and using the `skip_index` filter anywhere, use the `--no-skip-index` option.
47
+
48
+ {% highlight bash %}
49
+ $ yass build --no-skip-index
50
+ {% endhighlight %}
51
+
52
+ The `watch` command will continuously build as you make changes in `site/`, `layouts/`, and `templates/`.
53
+
54
+ {% highlight bash %}
55
+ $ yass watch # --no-skip-index works here too
56
+ {% endhighlight %}
57
+
58
+ ## Interested?
59
+
60
+ Keep reading about [layouts, templates]({{ "layouts-templates/index.html" | relative | strip_index }}), and [helpers]({{ "helpers/index.html" | relative | strip_index }}), or check out the code on [Github](https://github.com/jhollinger/yass)!
@@ -0,0 +1,64 @@
1
+ # Front Matter
2
+
3
+ Any file under `site/` may prepend YAML front matter to override the auto-generated title, set a layout, or set arbitrary attributes on the page for use in Liquid.
4
+
5
+ {% highlight yaml %}
6
+ ---
7
+ title: My Title
8
+ layout: foo
9
+ my_val: bar
10
+ ---
11
+ # File contents go here
12
+ {% endhighlight %}
13
+
14
+ # Layouts
15
+
16
+ Layouts are `.liquid` files in `layouts/`. The `content` variable contains the data to render.
17
+
18
+ {% highlight html %}
19
+ <!DOCTYPE html>
20
+ <html lang="en">
21
+ <head>
22
+ <title>{% echo "{{ page.title }}" %}</title>
23
+ </head>
24
+ <body>
25
+ {% echo "{{ content }}" %}
26
+ </body>
27
+ </html>
28
+ {% endhighlight %}
29
+
30
+ Layouts can be applied in the YAML front matter of any file under `site/`. If the following file is named `bar.html*` or `bar.md*`, it will look for a layout named `foo.html.liquid`:
31
+
32
+ {% highlight yaml %}
33
+ ---
34
+ layout: foo
35
+ ---
36
+ My content
37
+ {% endhighlight %}
38
+
39
+ ## Default layouts
40
+
41
+ If you create a layout named `default.<ext>.liquid`, Yass will apply it to any `.<ext>` files without a layout. For example, a layout named `default.html.liquid` will match `foo.html` or `foo.md.liquid`.
42
+
43
+ A file may eschew the default layout by setting `layout: false` in the YAML front matter.
44
+
45
+ # Templates
46
+
47
+ Templates live in `templates/` and can be used in any `.liquid` files.
48
+
49
+ *templates/greeting.liquid*
50
+
51
+ {% highlight html %}
52
+ <p>Hi, my name is {% echo "{{ name }}" %}</p>
53
+ {% endhighlight %}
54
+
55
+ Render the above template with:
56
+
57
+ {% highlight html %}
58
+ {% liquid
59
+ echo '{% render "greeting", name: "Pleck" %'
60
+ echo '}'
61
+ %}
62
+ {% endhighlight %}
63
+
64
+ NOTE: Liquid is pretty strict about template filenames. They must match `^[a-zA-Z0-9_]\.liquid$`.
@@ -0,0 +1,6 @@
1
+ <nav>
2
+ <a href="{{ "index.html" | relative | strip_index }}" class="home" >Home</a>
3
+ <a href="{{ "layouts-templates/index.html" | relative | strip_index }}">Layouts &amp; Templates</a>
4
+ <a href="{{ "helpers/index.html" | relative | strip_index }}">Helpers</a>
5
+ <a href="https://github.com/jhollinger/yass">Github</a>
6
+ </nav>
@@ -3,17 +3,16 @@ require 'optparse'
3
3
  module Yass
4
4
  module CLI
5
5
  module Helpers
6
- def self.get_cmd(argv)
7
- argv[0].to_s.to_sym
6
+ def self.get_cmd(argv) = argv[0].to_s.to_sym
7
+
8
+ def self.get_working_dir!(argv)
9
+ dir = argv[1] || Dir.pwd
10
+ find_path(dir, cwd: Dir.pwd)
8
11
  end
9
12
 
10
- def self.get_args!(argv, max: nil)
11
- args = argv[1..]
12
- if max && args.size > max
13
- $stderr.puts "Expected no more than #{max} args, found #{args.size}"
14
- exit 1
15
- end
16
- args
13
+ def self.find_path(path, cwd:)
14
+ path = Pathname.new(path)
15
+ path.relative? ? Pathname.new(cwd).join(path) : path
17
16
  end
18
17
 
19
18
  def self.get_opts!
@@ -35,23 +34,21 @@ module Yass
35
34
  opts.banner = %(
36
35
  Yet Another Static Site (generator) v#{VERSION}
37
36
 
38
- yass <command> [options] [path/to/dir]
37
+ yass <command> [path/to/dir] [options]
39
38
 
40
39
  Build the site:
41
- yass build
42
- yass build path/to/dir
40
+ yass build [path/to/dir] [options]
43
41
 
44
42
  Auto-build when files change:
45
- yass watch
46
- yass watch path/to/dir
43
+ yass watch [path/to/dir] [options]
47
44
 
48
45
  Create a new site:
49
- yass init <path/to/dir>
46
+ yass init [path/to/dir]
50
47
 
51
48
  Options:
52
49
  ).strip
53
50
  opts.on("--clean", "Remove unknown files from dist/ when bulding") { config.clean = true }
54
- opts.on("--dest=", "Build to a different directory") { |d| config.dest = d }
51
+ opts.on("--dest=DIR", "Build to a different directory") { |dir| config.dest = find_path(dir, cwd: Dir.pwd) }
55
52
  opts.on("--no-strip-index", "Disable the strip_index Liquid filter") { config.strip_index = false }
56
53
  opts.on("--debug", "Print stack traces") { config.debug = true }
57
54
  opts.on("-h", "--help", "Prints this help") { config.stdout.puts opts; exit }
@@ -3,11 +3,10 @@ require 'fileutils'
3
3
  module Yass
4
4
  module CLI
5
5
  module Runner
6
- INIT_DIR = Pathname.new(File.expand_path(File.join("..", "..", "..", "..", "site-template"), __FILE__))
6
+ INIT_DIR = Pathname.new(File.expand_path(File.join("..", "..", "..", "..", "docs-src"), __FILE__))
7
7
 
8
8
  def self.build(config, argv:)
9
- args = Helpers.get_args!(argv, max: 1)
10
- config.cwd = Pathname.new(args[0] || Dir.pwd)
9
+ config.cwd = Helpers.get_working_dir! argv
11
10
  Generator.new(config).generate!
12
11
  return 0
13
12
  rescue => e
@@ -17,16 +16,13 @@ module Yass
17
16
  end
18
17
 
19
18
  def self.init(config, argv:)
20
- args = Helpers.get_args!(argv, max: 1)
21
- config.cwd = Pathname.new(args[0] || Dir.pwd)
22
-
19
+ config.cwd = Helpers.get_working_dir! argv
23
20
  Dir[INIT_DIR.join("**/*.*")].each do |path|
24
21
  dest = config.cwd.join Pathname.new(path).relative_path_from(INIT_DIR)
25
22
  config.stdout.puts "Creating #{dest}"
26
23
  FileUtils.mkdir_p dest.dirname unless dest.dirname.exist?
27
24
  FileUtils.cp(path, dest) unless dest.exist?
28
25
  end
29
-
30
26
  return 0
31
27
  rescue => e
32
28
  raise e if config.debug
@@ -35,6 +31,7 @@ module Yass
35
31
  end
36
32
 
37
33
  def self.watch(config, argv:)
34
+ config.cwd = Helpers.get_working_dir! argv
38
35
  config.stdout.puts "Watching for changes..."
39
36
  watcher = Filewatcher.new([config.src_dir, config.layout_dir, config.template_dir].map(&:to_s))
40
37
  yield watcher if block_given?
data/lib/yass/config.rb CHANGED
@@ -37,9 +37,6 @@ module Yass
37
37
 
38
38
  private
39
39
 
40
- def get_dir(dir)
41
- dir = Pathname.new(dir)
42
- dir.absolute? ? dir : cwd.join(dir)
43
- end
40
+ def get_dir(dir) = CLI::Helpers.find_path(dir, cwd: cwd)
44
41
  end
45
42
  end
@@ -24,7 +24,7 @@ module Yass
24
24
 
25
25
  private
26
26
 
27
- def generate(source, outfile, content = source.path.read)
27
+ def generate(source, outfile, content = source.content)
28
28
  case outfile.extname
29
29
  when ".md"
30
30
  content = Kramdown::Document.new(content).to_html
@@ -1,23 +1,25 @@
1
1
  module Yass
2
2
  class LiquidTemplate
3
- def self.compile(config, name, src)
3
+ def self.compile(config, filename, src)
4
4
  template = Liquid::Template.parse(src, environment: config.liquid_env)
5
- new(name, template)
5
+ new(filename, template)
6
6
  end
7
7
 
8
- attr_reader :name
8
+ attr_reader :filename
9
9
 
10
- def initialize(name, template)
11
- @name = name
10
+ def initialize(filename, template)
11
+ @filename = filename
12
12
  @template = template
13
13
  end
14
14
 
15
+ def name = filename.sub(/\.liquid$/, "")
16
+
15
17
  def render(source)
16
18
  vars = { "page" => file_attrs(source), "files" => files_attrs(source.config.sources) }
17
19
  vars["content"] = yield if block_given?
18
20
  content = @template.render(vars, { strict_variables: true, strict_filters: true, registers: { source: source } })
19
21
  if @template.errors.any?
20
- source.config.stderr.puts "Errors found in #{name}:"
22
+ source.config.stderr.puts "Errors found in #{filename}:"
21
23
  source.config.stderr.puts @template.errors.map { |e| " #{e}" }.join("\n")
22
24
  end
23
25
  content
@@ -26,15 +28,16 @@ module Yass
26
28
  private
27
29
 
28
30
  def file_attrs(source)
29
- {
31
+ source.front_matter.merge({
30
32
  "title" => source.title,
33
+ "layout" => source.layout&.name,
31
34
  "path" => source.dest_path.to_s,
32
35
  "src_path" => source.src_path.to_s,
33
36
  "dirname" => source.dest_path.dirname.to_s,
34
37
  "filename" => source.dest_path.basename.to_s,
35
38
  "extname" => source.dest_path.basename.extname,
36
- "filesize" => File.stat(source.path).size,
37
- }
39
+ "filesize" => source.size,
40
+ })
38
41
  end
39
42
 
40
43
  def files_attrs(sources) = sources.map { |s| file_attrs s }
data/lib/yass/source.rb CHANGED
@@ -1,40 +1,64 @@
1
+ require 'yaml'
2
+
1
3
  module Yass
2
4
  class Source
3
5
  EXT_CONVERSIONS = {"md" => "html"}.freeze
4
- attr_reader :config, :path, :layout, :src_path, :dest_path, :outfile
6
+ YAML_HEADER = /\A---\s*\n/
7
+ FRONT_MATTER = /\A(?<matter>---\s*\n.*^---\s*\n?)(?<content>.+)?$/m
8
+
9
+ attr_reader :config, :front_matter, :path, :src_path, :dest_path, :outfile, :size
5
10
 
6
11
  def initialize(config, path)
7
12
  @config = config
8
13
  @path = path
9
14
  @src_path = path.relative_path_from config.src_dir
10
- dest_filename, @layout = parse_name
11
15
  @dest_path = src_path.dirname.join(dest_filename)
12
16
  @outfile = config.dest_dir.join(dest_path)
17
+ @size = File.stat(path).size
18
+
19
+ @front_matter, @content = parse_content
20
+ @title = @front_matter.delete "title" if front_matter.key? "title"
21
+ @layout_name = @front_matter.delete "layout" if front_matter.key? "layout"
22
+ end
23
+
24
+ def layout
25
+ return nil if @layout_name == false
26
+
27
+ ext = dest_path.extname
28
+ config.layout_cache["#{@layout_name}#{ext}"] || config.layout_cache["default#{ext}"]
13
29
  end
14
30
 
15
31
  def title
32
+ return @title if @title
33
+
16
34
  fname = dest_path.basename.sub(/\..+$/, "").to_s
17
35
  fname = src_path.dirname.basename.to_s if fname == "index"
18
36
  fname = "Home" if fname == "."
19
- fname.sub(/[_-]+/, " ").split(/ +/).map(&:capitalize).join(" ")
37
+ @title = fname.gsub(/[_-]+/, " ").split(/ +/).map(&:capitalize).join(" ")
20
38
  end
21
39
 
22
- def dynamic? = !!(/\.(liquid|md)(\..+)?$/ =~ path.basename.to_s || layout)
40
+ def dynamic? = !!(/\.(liquid|md)(\..+)?$/ =~ path.basename.to_s || layout || @has_front_matter)
41
+
42
+ def content = @content ||= path.read
23
43
 
24
44
  private
25
45
 
26
- def parse_name
46
+ def dest_filename
27
47
  name, exts = path.basename.to_s.split(".", 2)
28
- return name, nil if exts.nil?
29
-
30
- exts = exts.split(".").map { |x| EXT_CONVERSIONS[x] || x } - %w[liquid]
31
- return "#{name}.#{exts[0]}", config.layout_cache["default.#{exts[0]}"] if exts.size == 1
48
+ exts = (exts || "").split(".").map { |x| EXT_CONVERSIONS[x] || x } - %w[liquid]
49
+ [name, *exts].join(".")
50
+ end
32
51
 
33
- layout = config.layout_cache["#{exts[-2..].join(".")}"]
34
- exts.delete_at(-2) if layout
35
- layout ||= config.layout_cache["default.#{exts[-1]}"]
52
+ def parse_content
53
+ @has_front_matter = YAML_HEADER.match? path.read(10)
54
+ return {}, nil unless @has_front_matter
36
55
 
37
- return "#{name}.#{exts.join "."}", layout
56
+ @has_front_matter = true
57
+ captures = FRONT_MATTER.match(path.read).named_captures
58
+ return YAML.safe_load(captures["matter"].to_s), captures["content"].to_s
59
+ rescue Psych::SyntaxError => e
60
+ config.stderr.puts "Error parsing front matter for #{path}: #{e.message}"
61
+ return {}, ""
38
62
  end
39
63
  end
40
64
  end
data/lib/yass/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yass
2
- VERSION = "0.6.0".freeze
2
+ VERSION = "0.7.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Hollinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-11 00:00:00.000000000 Z
11
+ date: 2025-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: filewatcher
@@ -59,8 +59,22 @@ executables:
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - LICENSE
62
63
  - README.md
63
64
  - bin/yass
65
+ - docs-src/layouts/default.html.liquid
66
+ - docs-src/layouts/splash.html.liquid
67
+ - docs-src/site/assets/45-degree-fabric-dark.png
68
+ - docs-src/site/assets/Comic-Zine.woff
69
+ - docs-src/site/assets/highlight.min.js
70
+ - docs-src/site/assets/highlightjs-atom-one-dark.min.css
71
+ - docs-src/site/assets/main.css.liquid
72
+ - docs-src/site/favicon.png
73
+ - docs-src/site/helpers/index.md.liquid
74
+ - docs-src/site/index.md.liquid
75
+ - docs-src/site/layouts-templates/index.md.liquid
76
+ - docs-src/templates/asset_tags.liquid
77
+ - docs-src/templates/nav.liquid
64
78
  - lib/yass.rb
65
79
  - lib/yass/cli.rb
66
80
  - lib/yass/cli/helpers.rb
@@ -72,11 +86,6 @@ files:
72
86
  - lib/yass/liquid_template.rb
73
87
  - lib/yass/source.rb
74
88
  - lib/yass/version.rb
75
- - site-template/layouts/default.html.liquid
76
- - site-template/site/assets/highlight.min.css
77
- - site-template/site/assets/highlight.min.js
78
- - site-template/site/index.html.liquid
79
- - site-template/templates/asset_tags.liquid
80
89
  homepage: https://jhollinger.github.io/yass/
81
90
  licenses:
82
91
  - MIT
@@ -1,13 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>{{ page.title }}</title>
7
- {% render "asset_tags", files: files, page: page %}
8
- </head>
9
- <body>
10
- {{ content }}
11
- <script>hljs.highlightAll()</script>
12
- </body>
13
- </html>
@@ -1,9 +0,0 @@
1
- /*!
2
- Theme: Default
3
- Description: Original highlight.js style
4
- Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
5
- Maintainer: @highlightjs/core-team
6
- Website: https://highlightjs.org/
7
- License: see project LICENSE
8
- Touched: 2021
9
- */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
@@ -1 +0,0 @@
1
- <h1>Home</h1>