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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 649645d7b796ba02544a816464ff18efb5fdac5c3e914f16ce39ebde71337a37
4
- data.tar.gz: e6e2268d8733f20efb0f03f7b29c2a5a58e8e0deac5a0a4d796db3ca2ae78971
3
+ metadata.gz: da8870c6c309ac10a82d6e3cc5a4aa024d48a5c8e52ddb2b37c63ed99aeffe6a
4
+ data.tar.gz: 4d3344728ff23d2668e8da0b2cdf543587702fb5d7e096d3b090d548cd59b721
5
5
  SHA512:
6
- metadata.gz: e0eae7b97dbf4cc49a7e37812f867d0734e249058f560e58067be91d69abd4c2ce3e3a4e37eb5203555bc2135fc958a7c30c80cac67e1cd6c0551e44548c0c10
7
- data.tar.gz: df0d5bf462455417fed28d9725fee69bba326284e20e57532fb6a27a142363e8c91d4f670735f71d72a82a670dd2ec1a67d468829d043ef82304f336701b2690
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 `skip_index` filter anywhere, use the `--no-skip-index` option.
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-skip-index
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-skip-index
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.png" | relative }}" sizes="32x32">
8
- {% render "asset_tags", files: files, page: page %}
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
- <div id="wrapper">
12
- <header>
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
- {% render "nav", page: page %}
16
- </header>
14
+ {% render "nav", page: page %}
15
+ </header>
17
16
 
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>
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.png" | relative }}" sizes="32x32">
8
- {% render "asset_tags", files: files, page: page %}
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
- <div id="wrapper">
12
- <header>
13
- <div></div>
14
- {% render "nav", page: page %}
15
- </header>
11
+ <header>
12
+ <div></div>
13
+ {% render "nav", page: page %}
14
+ </header>
16
15
 
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>
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
- <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>
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
- #main {
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://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.
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 `skip_index` filter anywhere, use the `--no-skip-index` option.
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-skip-index
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-skip-index works here too
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 override the auto-generated title, set a layout, or set arbitrary attributes on the page for use in Liquid.
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: foo
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
- # File contents go here
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 %}
@@ -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,
@@ -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
- Generator.new(config).generate!
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 = config.cwd.join Pathname.new(path).relative_path_from(INIT_DIR)
22
- config.stdout.puts "Creating #{dest}"
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
- config.stdout.puts "Watching for changes..."
36
- watcher = Filewatcher.new([config.src_dir, config.layout_dir, config.template_dir].map(&:to_s))
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(config.cwd).to_s }.reject { |f| Dir.exist? f }
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
- config.stdout.puts "Building #{files.join ", "}"
44
- config.clear_cache!
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(:cwd, :src, :dest, :layouts, :templates, :clean, :strip_index, :stdin, :stdout, :stderr, :debug, keyword_init: true) do
3
- def src_dir = @src_dir ||= get_dir(src)
4
- def dest_dir = @dest_dir ||= get_dir(dest)
5
- def template_dir = @template_dir ||= get_dir(templates)
6
- def layout_dir = @layout_dir ||= get_dir(layouts)
7
-
8
- def clear_cache!
9
- @sources = nil
10
- @layout_cache = nil
11
- end
12
-
13
- def layout_cache
14
- @layout_cache ||= Dir[layout_dir.join("*.liquid")].each_with_object({}) do |path, acc|
15
- path = Pathname.new(path)
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
@@ -2,51 +2,31 @@ require 'fileutils'
2
2
 
3
3
  module Yass
4
4
  class Generator
5
- attr_reader :config
5
+ attr_reader :site
6
6
 
7
- def initialize(config)
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
- config.sources.each do |source|
14
- outfile = config.dest_dir.join(source.src_path)
11
+ site.sources.each do |source|
12
+ outfile = source.outfile
15
13
  if source.dynamic?
16
- outfile, content = generate(source, 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 config.clean
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 = config.sources.map { |s| config.dest_dir.join(s.dest_path).to_s }
46
- actual_files = Dir[config.dest_dir.join("**/*")].reject { |p| Dir.exist? p }
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 = config.sources.map { |s| s.outfile.dirname.to_s }.uniq
30
+ def dest_dirs = site.sources.map { |s| s.outfile.dirname.to_s }.uniq
51
31
  end
52
32
  end
@@ -9,9 +9,8 @@ module Yass
9
9
  end
10
10
 
11
11
  def strip_index(url)
12
- path = Pathname.new(url)
13
- strip = path.basename.to_s == "index.html" && strip_index?
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].config.strip_index
27
+ def strip_index? = context.registers[:source].site.strip_index
27
28
  end
28
29
  end
@@ -1,7 +1,7 @@
1
1
  module Yass
2
2
  class LiquidTemplate
3
- def self.compile(config, filename, src)
4
- template = Liquid::Template.parse(src, environment: config.liquid_env)
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 = { "page" => file_attrs(source), "files" => files_attrs(source.config.sources) }
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.config.stderr.puts "Errors found in #{filename}:"
23
- source.config.stderr.puts @template.errors.map { |e| " #{e}" }.join("\n")
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
- private
29
-
30
- def file_attrs(source)
31
- source.front_matter.merge({
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
- def files_attrs(sources) = sources.map { |s| file_attrs s }
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 :config, :front_matter, :path, :src_path, :dest_path, :outfile, :size
9
+ attr_reader :site, :front_matter, :path, :src_path, :dest_path
10
10
 
11
- def initialize(config, path)
12
- @config = config
11
+ def initialize(site, path)
12
+ @site = site
13
13
  @path = path
14
- @src_path = path.relative_path_from config.src_dir
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 = @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}"]
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
- config.stderr.puts "Error parsing front matter for #{path}: #{e.message}"
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
@@ -1,3 +1,3 @@
1
1
  module Yass
2
- VERSION = "0.7.0".freeze
2
+ VERSION = "0.9.0".freeze
3
3
  end
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 'liquid'
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.7.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-13 00:00:00.000000000 Z
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.png
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/
Binary file