yass 0.7.0 → 0.9.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 +4 -4
- data/README.md +3 -3
- data/docs-src/layouts/default.html.liquid +12 -15
- data/docs-src/layouts/splash.html.liquid +19 -26
- data/docs-src/site/assets/main.css.liquid +8 -9
- data/docs-src/site/favicon.ico +0 -0
- data/docs-src/site/helpers/index.md.liquid +13 -3
- data/docs-src/site/index.md.liquid +6 -4
- data/docs-src/site/layouts-templates/index.md.liquid +11 -3
- data/docs-src/templates/asset_tags.liquid +2 -2
- data/lib/yass/cli/helpers.rb +2 -1
- data/lib/yass/cli/runner.rb +13 -8
- data/lib/yass/config.rb +14 -40
- data/lib/yass/generator.rb +9 -29
- data/lib/yass/liquid_filters.rb +5 -4
- data/lib/yass/liquid_template.rb +37 -19
- data/lib/yass/renderer.rb +22 -0
- data/lib/yass/site.rb +48 -0
- data/lib/yass/source.rb +17 -17
- data/lib/yass/version.rb +1 -1
- data/lib/yass.rb +4 -1
- metadata +19 -3
- data/docs-src/site/favicon.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da8870c6c309ac10a82d6e3cc5a4aa024d48a5c8e52ddb2b37c63ed99aeffe6a
|
4
|
+
data.tar.gz: 4d3344728ff23d2668e8da0b2cdf543587702fb5d7e096d3b090d548cd59b721
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70d68c55e26cbdb96b54fa828fc79e57dba8642c79dfb44f39404c55906988b89a20171a97f15f7295780bfdb1556e998cfdb44ee1449eb2df794d7802b8ecad
|
7
|
+
data.tar.gz: cbc1bfc9cf96bebc38d460a7ca8a5cab7f31207345bd2d2e4fd5cd900040849d9adbc53a54509d7d960611bcdb0be22d8ce9473efa767ea61b6d394aa2f0c3a6
|
data/README.md
CHANGED
@@ -32,16 +32,16 @@ The built site will be placed into `dist`.
|
|
32
32
|
yass build
|
33
33
|
```
|
34
34
|
|
35
|
-
NOTE If you're building for webserverless, local viewing, and using the `
|
35
|
+
NOTE If you're building for webserverless, local viewing, and using the `strip_index` filter anywhere, use the `--no-strip-index` option.
|
36
36
|
|
37
37
|
```bash
|
38
|
-
yass build --no-
|
38
|
+
yass build --no-strip-index
|
39
39
|
```
|
40
40
|
|
41
41
|
Use the `watch` command to continually build your site as files change.
|
42
42
|
|
43
43
|
```bash
|
44
|
-
yass watch # also supports --no-
|
44
|
+
yass watch # also supports --no-strip-index
|
45
45
|
```
|
46
46
|
|
47
47
|
## License
|
@@ -4,27 +4,24 @@
|
|
4
4
|
<meta charset="utf-8">
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
6
|
<title>{{ page.title }}</title>
|
7
|
-
<link rel="icon" href="{{ "favicon.
|
8
|
-
{% render "asset_tags",
|
7
|
+
<link rel="icon" href="{{ "favicon.ico" | relative }}" sizes="32x32">
|
8
|
+
{% render "asset_tags", site: site, page: page %}
|
9
9
|
</head>
|
10
10
|
<body>
|
11
|
-
<
|
12
|
-
<
|
13
|
-
<h1><a href="{{ "index.html" | relative | strip_index }}">Yass</a></h1>
|
11
|
+
<header>
|
12
|
+
<h1><a href="{{ "index.html" | relative | strip_index }}">Yass</a></h1>
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
{% render "nav", page: page %}
|
15
|
+
</header>
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
<div class="flex"></div>
|
24
|
-
</section>
|
25
|
-
</div>
|
17
|
+
<main class="flex">
|
18
|
+
<div class="content">
|
19
|
+
{{ content }}
|
20
|
+
</div>
|
21
|
+
</main>
|
26
22
|
|
27
23
|
<footer></footer>
|
24
|
+
|
28
25
|
<script>hljs.highlightAll()</script>
|
29
26
|
</body>
|
30
27
|
</html>
|
@@ -4,37 +4,30 @@
|
|
4
4
|
<meta charset="utf-8">
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
6
|
<title>{{ page.title }}</title>
|
7
|
-
<link rel="icon" href="{{ "favicon.
|
8
|
-
{% render "asset_tags",
|
7
|
+
<link rel="icon" href="{{ "favicon.ico" | relative }}" sizes="32x32">
|
8
|
+
{% render "asset_tags", site: site, page: page %}
|
9
9
|
</head>
|
10
10
|
<body>
|
11
|
-
<
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
</header>
|
11
|
+
<header>
|
12
|
+
<div></div>
|
13
|
+
{% render "nav", page: page %}
|
14
|
+
</header>
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
<div class="flex"></div>
|
26
|
-
</section>
|
16
|
+
<section id="hero">
|
17
|
+
<div id="title">Yass</div>
|
18
|
+
<div id="subtitle">
|
19
|
+
<p>Yet Another Static Site (generator)</p>
|
20
|
+
</div>
|
21
|
+
</section>
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
<main class="flex">
|
24
|
+
<div class="content">
|
25
|
+
{{ content }}
|
26
|
+
</div>
|
27
|
+
</main>
|
28
|
+
|
29
|
+
<footer></footer>
|
35
30
|
|
36
|
-
<footer></footer>
|
37
|
-
</div>
|
38
31
|
<script>hljs.highlightAll()</script>
|
39
32
|
</body>
|
40
33
|
</html>
|
@@ -27,6 +27,12 @@
|
|
27
27
|
}
|
28
28
|
|
29
29
|
body {
|
30
|
+
display: flex;
|
31
|
+
flex-direction: column;
|
32
|
+
flex-wrap: nowrap;
|
33
|
+
width: 100vw;
|
34
|
+
min-height: 100vh;
|
35
|
+
|
30
36
|
background-color: var(--dark-grey);
|
31
37
|
background-image: var(--bg-image);
|
32
38
|
color: var(--off-white);
|
@@ -67,14 +73,6 @@ a {
|
|
67
73
|
}
|
68
74
|
ul { margin: 1rem 0 1rem 1rem }
|
69
75
|
|
70
|
-
#wrapper {
|
71
|
-
display: flex;
|
72
|
-
flex-direction: column;
|
73
|
-
flex-wrap: nowrap;
|
74
|
-
width: 100vw;
|
75
|
-
min-height: 100vh;
|
76
|
-
}
|
77
|
-
|
78
76
|
#hero {
|
79
77
|
display: flex;
|
80
78
|
flex-direction: column;
|
@@ -101,9 +99,10 @@ h3 { font-size: 1.75rem; margin: 1.5rem 0 0.5rem 0 }
|
|
101
99
|
h4 { font-size: 1.5rem; margin: 1.5rem 0 0.5rem 0 }
|
102
100
|
h5 { font-size: 1.25rem; margin: 1.5rem 0 0.5rem 0 }
|
103
101
|
|
104
|
-
|
102
|
+
main {
|
105
103
|
display: flex;
|
106
104
|
flex-direction: row;
|
105
|
+
justify-content: center;
|
107
106
|
}
|
108
107
|
|
109
108
|
.content {
|
Binary file
|
@@ -16,18 +16,20 @@ An object representing the current page. Properties:
|
|
16
16
|
* `filename` Name of file (e.g. *zorp.html* from *foo/bar/zorp.html*)
|
17
17
|
* `extname` File extension (e.g. *.html* from *foo/bar/zorp.html*)
|
18
18
|
* `filesize` Size of file in bytes
|
19
|
+
* `published` If the file is published or not
|
20
|
+
* `content` The file content
|
19
21
|
* Any other value defined in the file's YAML front matter
|
20
22
|
|
21
23
|
{% highlight html %}
|
22
24
|
<h1>{% echo "{{" %} page.title {% echo "}}" %}</h1>
|
23
25
|
{% endhighlight %}
|
24
26
|
|
25
|
-
### files
|
27
|
+
### site.files
|
26
28
|
|
27
|
-
Any array of all files that will be written `dist/`. Same properties as `page`.
|
29
|
+
Any array of all (published) files that will be written `dist/`. Same properties as `page`.
|
28
30
|
|
29
31
|
{% highlight html %}
|
30
|
-
{% echo '{% assign css_files = files | where: "extname", ".css" %' %}}
|
32
|
+
{% echo '{% assign css_files = site.files | where: "extname", ".css" %' %}}
|
31
33
|
{% echo "{% for file in css_files %" %}}
|
32
34
|
<link rel="stylesheet" href="{% echo "{{ file.path | relative }}" %}">
|
33
35
|
{% echo "{% endfor %" %}}
|
@@ -69,6 +71,14 @@ Works like Liquid's built-it `where`, but accepts a regular expression.
|
|
69
71
|
{% echo '{% assign posts = where_match: "path", "^posts/.+\.html$" %' %}}
|
70
72
|
{% endhighlight %}
|
71
73
|
|
74
|
+
### where_not
|
75
|
+
|
76
|
+
Works like Liquid's built-it `where`, but returns object that *don't* match.
|
77
|
+
|
78
|
+
{% highlight %}
|
79
|
+
{% echo '{% assign posts = where_not: "hidden", true %' %}}
|
80
|
+
{% endhighlight %}
|
81
|
+
|
72
82
|
## Tags
|
73
83
|
|
74
84
|
### highlight
|
@@ -3,7 +3,7 @@ layout: splash
|
|
3
3
|
---
|
4
4
|
# What is Yass?
|
5
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://
|
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://github.github.com/gfm/)) 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
7
|
|
8
8
|
The **one** opinion Yass holds is that **you** should decide everything. There's zero configuration and no conventions to learn!
|
9
9
|
|
@@ -43,18 +43,20 @@ $ yass build
|
|
43
43
|
|
44
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
45
|
|
46
|
-
If you're building for webserverless, local viewing, and using the `
|
46
|
+
If you're building for webserverless, local viewing, and using the `strip_index` filter anywhere, use the `--no-strip-index` option.
|
47
47
|
|
48
48
|
{% highlight bash %}
|
49
|
-
$ yass build --no-
|
49
|
+
$ yass build --no-strip-index
|
50
50
|
{% endhighlight %}
|
51
51
|
|
52
52
|
The `watch` command will continuously build as you make changes in `site/`, `layouts/`, and `templates/`.
|
53
53
|
|
54
54
|
{% highlight bash %}
|
55
|
-
$ yass watch # --no-
|
55
|
+
$ yass watch # --no-strip-index works here too
|
56
56
|
{% endhighlight %}
|
57
57
|
|
58
|
+
Run `yass --help` for all options.
|
59
|
+
|
58
60
|
## Interested?
|
59
61
|
|
60
62
|
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)!
|
@@ -1,14 +1,22 @@
|
|
1
1
|
# Front Matter
|
2
2
|
|
3
|
-
Any file under `site/` may prepend YAML front matter to
|
3
|
+
Any file under `site/` may prepend YAML front matter to tweak how that file is rendered. All fields are optional.
|
4
4
|
|
5
5
|
{% highlight yaml %}
|
6
6
|
---
|
7
|
+
# The default title is based on the filename
|
7
8
|
title: My Title
|
8
|
-
layout
|
9
|
+
# Override the default layout, or disable the layout with false
|
10
|
+
layout: home
|
11
|
+
# If this file isn't ready yet, set to false
|
12
|
+
published: true
|
13
|
+
|
14
|
+
# Arbitrary values will be available on `page` and `site.files`
|
9
15
|
my_val: bar
|
10
16
|
---
|
11
|
-
|
17
|
+
<!DOCTYPE html>
|
18
|
+
<html lang="en">
|
19
|
+
...
|
12
20
|
{% endhighlight %}
|
13
21
|
|
14
22
|
# Layouts
|
@@ -1,9 +1,9 @@
|
|
1
|
-
{% assign css_files = files | where: "extname", ".css" -%}
|
1
|
+
{% assign css_files = site.files | where: "extname", ".css" -%}
|
2
2
|
{% for file in css_files %}
|
3
3
|
<link rel="stylesheet" href="{{ file.path | relative }}">
|
4
4
|
{% endfor %}
|
5
5
|
|
6
|
-
{% assign js_files = files | where: "extname", ".js" -%}
|
6
|
+
{% assign js_files = site.files | where: "extname", ".js" -%}
|
7
7
|
{% for file in js_files %}
|
8
8
|
<script src="{{ file.path | relative }}"></script>
|
9
9
|
{% endfor %}
|
data/lib/yass/cli/helpers.rb
CHANGED
@@ -49,6 +49,7 @@ yass <command> [path/to/dir] [options]
|
|
49
49
|
).strip
|
50
50
|
opts.on("--clean", "Remove unknown files from dist/ when bulding") { config.clean = true }
|
51
51
|
opts.on("--dest=DIR", "Build to a different directory") { |dir| config.dest = find_path(dir, cwd: Dir.pwd) }
|
52
|
+
opts.on("--drafts", "Include unpublished files in build") { config.include_drafts = true }
|
52
53
|
opts.on("--no-strip-index", "Disable the strip_index Liquid filter") { config.strip_index = false }
|
53
54
|
opts.on("--debug", "Print stack traces") { config.debug = true }
|
54
55
|
opts.on("-h", "--help", "Prints this help") { config.stdout.puts opts; exit }
|
@@ -63,8 +64,8 @@ yass <command> [path/to/dir] [options]
|
|
63
64
|
templates: "templates",
|
64
65
|
dest: "dist",
|
65
66
|
clean: false,
|
67
|
+
include_drafts: false,
|
66
68
|
strip_index: true,
|
67
|
-
stdin: $stdin,
|
68
69
|
stdout: $stdout,
|
69
70
|
stderr: $stderr,
|
70
71
|
debug: false,
|
data/lib/yass/cli/runner.rb
CHANGED
@@ -7,7 +7,8 @@ module Yass
|
|
7
7
|
|
8
8
|
def self.build(config, argv:)
|
9
9
|
config.cwd = Helpers.get_working_dir! argv
|
10
|
-
|
10
|
+
site = Site.new(config)
|
11
|
+
Generator.new(site).generate!
|
11
12
|
return 0
|
12
13
|
rescue => e
|
13
14
|
raise e if config.debug
|
@@ -17,9 +18,11 @@ module Yass
|
|
17
18
|
|
18
19
|
def self.init(config, argv:)
|
19
20
|
config.cwd = Helpers.get_working_dir! argv
|
21
|
+
site = Site.new(config)
|
22
|
+
|
20
23
|
Dir[INIT_DIR.join("**/*.*")].each do |path|
|
21
|
-
dest =
|
22
|
-
|
24
|
+
dest = site.cwd.join Pathname.new(path).relative_path_from(INIT_DIR)
|
25
|
+
site.stdout.puts "Creating #{dest}"
|
23
26
|
FileUtils.mkdir_p dest.dirname unless dest.dirname.exist?
|
24
27
|
FileUtils.cp(path, dest) unless dest.exist?
|
25
28
|
end
|
@@ -32,16 +35,18 @@ module Yass
|
|
32
35
|
|
33
36
|
def self.watch(config, argv:)
|
34
37
|
config.cwd = Helpers.get_working_dir! argv
|
35
|
-
|
36
|
-
|
38
|
+
site = Site.new(config)
|
39
|
+
|
40
|
+
site.stdout.puts "Watching for changes..."
|
41
|
+
watcher = Filewatcher.new([site.src_dir, site.layout_dir, site.template_dir].map(&:to_s))
|
37
42
|
yield watcher if block_given?
|
38
43
|
|
39
44
|
Yass::CLI::Runner.build(config, argv: argv)
|
40
45
|
watcher.watch do |changes|
|
41
|
-
files = changes.map { |f, _| Pathname.new(f).relative_path_from(
|
46
|
+
files = changes.map { |f, _| Pathname.new(f).relative_path_from(site.cwd).to_s }.reject { |f| Dir.exist? f }
|
42
47
|
# TODO use \r?
|
43
|
-
|
44
|
-
|
48
|
+
site.stdout.puts "Building #{files.join ", "}"
|
49
|
+
site.clear_cache!
|
45
50
|
Yass::CLI::Runner.build(config, argv: argv)
|
46
51
|
end
|
47
52
|
return 0
|
data/lib/yass/config.rb
CHANGED
@@ -1,42 +1,16 @@
|
|
1
1
|
module Yass
|
2
|
-
Config = Struct.new(
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
name = path.basename.to_s
|
17
|
-
acc[name.sub(/\.liquid$/, "")] = LiquidTemplate.compile(self, name, path.read)
|
18
|
-
end.freeze
|
19
|
-
end
|
20
|
-
|
21
|
-
def sources
|
22
|
-
@sources ||= Dir[src_dir.join("**", "*")]
|
23
|
-
.reject { |path| Dir.exist? path }
|
24
|
-
.map { |path| Pathname.new path }
|
25
|
-
.map { |path| Source.new(self, path) }
|
26
|
-
end
|
27
|
-
|
28
|
-
def liquid_env
|
29
|
-
@liquid_env ||= Liquid::Environment.build do |env|
|
30
|
-
env.error_mode = :strict
|
31
|
-
env.file_system = Liquid::LocalFileSystem.new(template_dir.to_s, "%s.liquid")
|
32
|
-
env.register_filter LiquidFilters
|
33
|
-
env.register_tag 'highlight', LiquidTags::Highlight
|
34
|
-
env.register_tag 'render_content', LiquidTags::RenderContent
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def get_dir(dir) = CLI::Helpers.find_path(dir, cwd: cwd)
|
41
|
-
end
|
2
|
+
Config = Struct.new(
|
3
|
+
:cwd,
|
4
|
+
:src,
|
5
|
+
:dest,
|
6
|
+
:layouts,
|
7
|
+
:templates,
|
8
|
+
:clean,
|
9
|
+
:include_drafts,
|
10
|
+
:strip_index,
|
11
|
+
:stdout,
|
12
|
+
:stderr,
|
13
|
+
:debug,
|
14
|
+
keyword_init: true
|
15
|
+
)
|
42
16
|
end
|
data/lib/yass/generator.rb
CHANGED
@@ -2,51 +2,31 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
module Yass
|
4
4
|
class Generator
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :site
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@config = config
|
9
|
-
end
|
7
|
+
def initialize(site) = @site = site
|
10
8
|
|
11
9
|
def generate!
|
12
10
|
dest_dirs.each { |dir| FileUtils.mkdir_p dir }
|
13
|
-
|
14
|
-
outfile =
|
11
|
+
site.sources.each do |source|
|
12
|
+
outfile = source.outfile
|
15
13
|
if source.dynamic?
|
16
|
-
outfile
|
17
|
-
outfile.write content
|
14
|
+
outfile.write Renderer.new(source).render
|
18
15
|
else
|
19
16
|
FileUtils.cp(source.path, outfile)
|
20
17
|
end
|
21
18
|
end
|
22
|
-
clean if
|
19
|
+
clean if site.clean
|
23
20
|
end
|
24
21
|
|
25
22
|
private
|
26
23
|
|
27
|
-
def generate(source, outfile, content = source.content)
|
28
|
-
case outfile.extname
|
29
|
-
when ".md"
|
30
|
-
content = Kramdown::Document.new(content).to_html
|
31
|
-
return generate(source, outfile.sub(/\.md$/, ".html"), content)
|
32
|
-
when ".liquid"
|
33
|
-
template = LiquidTemplate.compile(config, source.src_path, content)
|
34
|
-
content = template.render(source)
|
35
|
-
return generate(source, outfile.sub(/\.liquid$/, ""), content)
|
36
|
-
else
|
37
|
-
return outfile, content if source.layout.nil?
|
38
|
-
|
39
|
-
page = source.layout.render(source) { content }
|
40
|
-
return outfile.dirname.join(source.dest_path.basename), page
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
24
|
def clean
|
45
|
-
expected_files =
|
46
|
-
actual_files = Dir[
|
25
|
+
expected_files = site.sources.map { |s| site.dest_dir.join(s.dest_path).to_s }
|
26
|
+
actual_files = Dir[site.dest_dir.join("**/*")].reject { |p| Dir.exist? p }
|
47
27
|
(actual_files - expected_files).each { |f| FileUtils.rm f }
|
48
28
|
end
|
49
29
|
|
50
|
-
def dest_dirs =
|
30
|
+
def dest_dirs = site.sources.map { |s| s.outfile.dirname.to_s }.uniq
|
51
31
|
end
|
52
32
|
end
|
data/lib/yass/liquid_filters.rb
CHANGED
@@ -9,9 +9,8 @@ module Yass
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def strip_index(url)
|
12
|
-
path =
|
13
|
-
|
14
|
-
strip ? path.dirname.to_s : path.to_s
|
12
|
+
path = strip_index? ? url.sub(%r'/?index\.html([\?#][^/]*)?$', '/\1') : url
|
13
|
+
path == "/" ? "." : path
|
15
14
|
end
|
16
15
|
|
17
16
|
def match(str, regex) = Regexp.new(regex).match? str
|
@@ -21,8 +20,10 @@ module Yass
|
|
21
20
|
objects.select { |obj| regex =~ obj[field].to_s }
|
22
21
|
end
|
23
22
|
|
23
|
+
def where_not(objects, field, value) = objects.reject { |obj| obj.send(field) == value }
|
24
|
+
|
24
25
|
private
|
25
26
|
|
26
|
-
def strip_index? = context.registers[:source].
|
27
|
+
def strip_index? = context.registers[:source].site.strip_index
|
27
28
|
end
|
28
29
|
end
|
data/lib/yass/liquid_template.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Yass
|
2
2
|
class LiquidTemplate
|
3
|
-
def self.compile(
|
4
|
-
template = Liquid::Template.parse(src, environment:
|
3
|
+
def self.compile(site, filename, src)
|
4
|
+
template = Liquid::Template.parse(src, environment: site.liquid_env)
|
5
5
|
new(filename, template)
|
6
6
|
end
|
7
7
|
|
@@ -15,31 +15,49 @@ module Yass
|
|
15
15
|
def name = filename.sub(/\.liquid$/, "")
|
16
16
|
|
17
17
|
def render(source)
|
18
|
-
vars = {
|
18
|
+
vars = {}
|
19
|
+
vars["page"] = SourceDrop.new(source)
|
20
|
+
vars["site"] = SiteDrop.new(source.site)
|
19
21
|
vars["content"] = yield if block_given?
|
22
|
+
|
20
23
|
content = @template.render(vars, { strict_variables: true, strict_filters: true, registers: { source: source } })
|
21
24
|
if @template.errors.any?
|
22
|
-
source.
|
23
|
-
source.
|
25
|
+
source.site.stderr.puts "Errors found in #{filename}:"
|
26
|
+
source.site.stderr.puts @template.errors.map { |e| " #{e}" }.join("\n")
|
24
27
|
end
|
25
28
|
content
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
"title" => source.title,
|
33
|
-
"layout" => source.layout&.name,
|
34
|
-
"path" => source.dest_path.to_s,
|
35
|
-
"src_path" => source.src_path.to_s,
|
36
|
-
"dirname" => source.dest_path.dirname.to_s,
|
37
|
-
"filename" => source.dest_path.basename.to_s,
|
38
|
-
"extname" => source.dest_path.basename.extname,
|
39
|
-
"filesize" => source.size,
|
40
|
-
})
|
31
|
+
class SiteDrop < Liquid::Drop
|
32
|
+
def initialize(site) = @site = site
|
33
|
+
|
34
|
+
def files = @files ||= @site.sources.map { |s| SourceDrop.new(s) }
|
41
35
|
end
|
42
36
|
|
43
|
-
|
37
|
+
class SourceDrop < Liquid::Drop
|
38
|
+
def initialize(source) = @source = source
|
39
|
+
|
40
|
+
def title = @source.title
|
41
|
+
|
42
|
+
def layout = @source.layout&.name
|
43
|
+
|
44
|
+
def path = @source.dest_path.to_s
|
45
|
+
|
46
|
+
def src_path = @source.src_path.to_s
|
47
|
+
|
48
|
+
def dirname = @source.dest_path.dirname.to_s
|
49
|
+
|
50
|
+
def filename = @source.dest_path.basename.to_s
|
51
|
+
|
52
|
+
def extname = @source.dest_path.extname.to_s
|
53
|
+
|
54
|
+
def filesize = @source.size
|
55
|
+
|
56
|
+
def published = @source.published?
|
57
|
+
|
58
|
+
def content = Renderer.new(@source).render(layout: false)
|
59
|
+
|
60
|
+
def method_missing(attr) = @source.front_matter[attr.to_s]
|
61
|
+
end
|
44
62
|
end
|
45
63
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Yass
|
2
|
+
class Renderer
|
3
|
+
attr_reader :source
|
4
|
+
|
5
|
+
def initialize(source) = @source = source
|
6
|
+
|
7
|
+
def render(outfile = source.site.dest_dir.join(source.src_path), content = source.content, layout: true)
|
8
|
+
case outfile.extname
|
9
|
+
when ".md"
|
10
|
+
content = Kramdown::Document.new(content, input: "GFM").to_html
|
11
|
+
return render(outfile.sub(/\.md$/, ".html"), content, layout: layout)
|
12
|
+
when ".liquid"
|
13
|
+
template = LiquidTemplate.compile(source.site, source.src_path, content)
|
14
|
+
content = template.render(source)
|
15
|
+
return render(outfile.sub(/\.liquid$/, ""), content, layout: layout)
|
16
|
+
else
|
17
|
+
return content if source.layout.nil? || !layout
|
18
|
+
return source.layout.render(source) { content }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/yass/site.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Yass
|
4
|
+
class Site < SimpleDelegator
|
5
|
+
def initialize(config) = super config.dup.freeze
|
6
|
+
|
7
|
+
def src_dir = @src_dir ||= get_dir(src)
|
8
|
+
def dest_dir = @dest_dir ||= get_dir(dest)
|
9
|
+
def template_dir = @template_dir ||= get_dir(templates)
|
10
|
+
def layout_dir = @layout_dir ||= get_dir(layouts)
|
11
|
+
|
12
|
+
def clear_cache!
|
13
|
+
@sources = nil
|
14
|
+
@layout_cache = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def layout_cache
|
18
|
+
@layout_cache ||= Dir[layout_dir.join("*.liquid")].each_with_object({}) do |path, acc|
|
19
|
+
path = Pathname.new(path)
|
20
|
+
name = path.basename.to_s
|
21
|
+
acc[name.sub(/\.liquid$/, "")] = LiquidTemplate.compile(self, name, path.read)
|
22
|
+
end.freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
def sources
|
26
|
+
@sources ||= Dir[src_dir.join("**", "*")]
|
27
|
+
.reject { |path| Dir.exist? path }
|
28
|
+
.map { |path| Pathname.new path }
|
29
|
+
.map { |path| Source.new(self, path) }
|
30
|
+
.select { |source| source.published? || include_drafts }
|
31
|
+
.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
def liquid_env
|
35
|
+
@liquid_env ||= Liquid::Environment.build do |env|
|
36
|
+
env.error_mode = :strict
|
37
|
+
env.file_system = Liquid::LocalFileSystem.new(template_dir.to_s, "%s.liquid")
|
38
|
+
env.register_filter LiquidFilters
|
39
|
+
env.register_tag 'highlight', LiquidTags::Highlight
|
40
|
+
env.register_tag 'render_content', LiquidTags::RenderContent
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def get_dir(dir) = CLI::Helpers.find_path(dir, cwd: cwd)
|
47
|
+
end
|
48
|
+
end
|
data/lib/yass/source.rb
CHANGED
@@ -6,26 +6,18 @@ module Yass
|
|
6
6
|
YAML_HEADER = /\A---\s*\n/
|
7
7
|
FRONT_MATTER = /\A(?<matter>---\s*\n.*^---\s*\n?)(?<content>.+)?$/m
|
8
8
|
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :site, :front_matter, :path, :src_path, :dest_path
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@
|
11
|
+
def initialize(site, path)
|
12
|
+
@site = site
|
13
13
|
@path = path
|
14
|
-
@src_path = path.relative_path_from
|
14
|
+
@src_path = path.relative_path_from site.src_dir
|
15
15
|
@dest_path = src_path.dirname.join(dest_filename)
|
16
|
-
@outfile = config.dest_dir.join(dest_path)
|
17
|
-
@size = File.stat(path).size
|
18
16
|
|
19
17
|
@front_matter, @content = parse_content
|
20
|
-
@title =
|
21
|
-
@layout_name =
|
22
|
-
|
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}"]
|
18
|
+
@title = front_matter.delete "title" if front_matter.key? "title"
|
19
|
+
@layout_name = front_matter.delete "layout" if front_matter.key? "layout"
|
20
|
+
@layout_name = "default" if @layout_name.nil?
|
29
21
|
end
|
30
22
|
|
31
23
|
def title
|
@@ -37,10 +29,18 @@ module Yass
|
|
37
29
|
@title = fname.gsub(/[_-]+/, " ").split(/ +/).map(&:capitalize).join(" ")
|
38
30
|
end
|
39
31
|
|
32
|
+
def layout = @layout_name == false ? nil : site.layout_cache["#{@layout_name}#{dest_path.extname}"]
|
33
|
+
|
40
34
|
def dynamic? = !!(/\.(liquid|md)(\..+)?$/ =~ path.basename.to_s || layout || @has_front_matter)
|
41
35
|
|
42
36
|
def content = @content ||= path.read
|
43
37
|
|
38
|
+
def outfile = site.dest_dir.join(dest_path)
|
39
|
+
|
40
|
+
def published? = front_matter["published"].nil? ? true : !!front_matter["published"]
|
41
|
+
|
42
|
+
def size = @size ||= File.stat(path).size
|
43
|
+
|
44
44
|
private
|
45
45
|
|
46
46
|
def dest_filename
|
@@ -55,9 +55,9 @@ module Yass
|
|
55
55
|
|
56
56
|
@has_front_matter = true
|
57
57
|
captures = FRONT_MATTER.match(path.read).named_captures
|
58
|
-
return YAML.safe_load(captures["matter"].to_s), captures["content"].to_s
|
58
|
+
return YAML.safe_load(captures["matter"].to_s) || {}, captures["content"].to_s
|
59
59
|
rescue Psych::SyntaxError => e
|
60
|
-
|
60
|
+
site.stderr.puts "Error parsing front matter for #{path}: #{e.message}"
|
61
61
|
return {}, ""
|
62
62
|
end
|
63
63
|
end
|
data/lib/yass/version.rb
CHANGED
data/lib/yass.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'filewatcher'
|
3
|
+
require 'liquid' # MUST be loaded before kramdown-parser-gfm for some reason
|
3
4
|
require 'kramdown'
|
4
|
-
require '
|
5
|
+
require 'kramdown-parser-gfm'
|
5
6
|
|
6
7
|
module Yass
|
7
8
|
autoload :CLI, 'yass/cli'
|
@@ -10,6 +11,8 @@ module Yass
|
|
10
11
|
autoload :LiquidFilters, 'yass/liquid_filters'
|
11
12
|
autoload :LiquidTags, 'yass/liquid_tags'
|
12
13
|
autoload :LiquidTemplate, 'yass/liquid_template'
|
14
|
+
autoload :Renderer, 'yass/renderer'
|
15
|
+
autoload :Site, 'yass/site'
|
13
16
|
autoload :Source, 'yass/source'
|
14
17
|
autoload :VERSION, 'yass/version'
|
15
18
|
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.
|
4
|
+
version: 0.9.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
|
+
date: 2025-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: filewatcher
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kramdown-parser-gfm
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: liquid
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -69,7 +83,7 @@ files:
|
|
69
83
|
- docs-src/site/assets/highlight.min.js
|
70
84
|
- docs-src/site/assets/highlightjs-atom-one-dark.min.css
|
71
85
|
- docs-src/site/assets/main.css.liquid
|
72
|
-
- docs-src/site/favicon.
|
86
|
+
- docs-src/site/favicon.ico
|
73
87
|
- docs-src/site/helpers/index.md.liquid
|
74
88
|
- docs-src/site/index.md.liquid
|
75
89
|
- docs-src/site/layouts-templates/index.md.liquid
|
@@ -84,6 +98,8 @@ files:
|
|
84
98
|
- lib/yass/liquid_filters.rb
|
85
99
|
- lib/yass/liquid_tags.rb
|
86
100
|
- lib/yass/liquid_template.rb
|
101
|
+
- lib/yass/renderer.rb
|
102
|
+
- lib/yass/site.rb
|
87
103
|
- lib/yass/source.rb
|
88
104
|
- lib/yass/version.rb
|
89
105
|
homepage: https://jhollinger.github.io/yass/
|
data/docs-src/site/favicon.png
DELETED
Binary file
|