yass 0.0.1 → 0.2.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: 8b9e4145b2a4bd254b30c955ddfcceb27a5d921c3efbc8cffc86daae9e1baa5c
4
- data.tar.gz: 439dd4814f60ae2621674bcd179e49a47ff9c899513ef4da4307036ee1bbe26f
3
+ metadata.gz: 664e04a8abbd128da8902e65d83a0ed305010982f18e30d24c08571ee70cd9d0
4
+ data.tar.gz: 3c1f2151246b638cdc23bb340abef6ae3136adc677fa4abd1f0a3e374fcfbd78
5
5
  SHA512:
6
- metadata.gz: 2e41fb008955497801275a312189ace07d3f8488d3d1a7f88e772dd75a22710e12cad80b465cf8725b08c4fc3c2a6fcbc211a1adda7f697cd072cc5e9ae0f5c0
7
- data.tar.gz: ee98de21f39a6d63c4dbe130af0d52117c83aebd1ba352c57419f819f3e4eab0523207f37c07c348a3a2c2679e9b50a657bb1c61fce270b7cfd9a9c940e7b45a
6
+ metadata.gz: 07c5522d3aa8e206d3fb49681378ec00e41b7009583ab245d905658927111a8f09f424a4915564967ee9a93bab225ed0ef78100b695bb23c7432b053d4117a3e
7
+ data.tar.gz: 0ba17529c477f1755e9e11a2976c44bd2155e8639ed205062b4a78e0057c30efe82f254f1af29efe9d5a546826953712653f641c35c2d84ba590055304b21860
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Yet Another Static Site (generator)
4
4
 
5
- Yass is an incredibly unopinioanted static site generator. Here's how it works:
5
+ Yass is an incredibly un-opinionated static site generator. Here's how it works:
6
6
 
7
- * You write everything by hand under `site/`.
7
+ * Write everything by hand under `site/`.
8
8
  * Everything under `site/` is copied to `dist/`.
9
9
  * [Markdown](https://commonmark.org/) (`.md`) and [Liquid](https://shopify.github.io/liquid/) (`.liquid`) files are processed.
10
10
  * Liquid layouts and templates can be placed into `layouts/` and `templates/`.
@@ -14,6 +14,8 @@ Yass is an incredibly unopinioanted static site generator. Here's how it works:
14
14
 
15
15
  ## Getting started
16
16
 
17
+ Starting from an empty page isn't fun, so `yass init` will create a skeleton site for you.
18
+
17
19
  ```bash
18
20
  $ gem install yass
19
21
  $ yass init blog
@@ -40,7 +42,97 @@ If you're building for local viewing, use the `--local` option. It ensures any g
40
42
  yass build --local
41
43
  ```
42
44
 
43
- ## License & copywrite
45
+ Use the `watch` command to continually build your site as files change.
46
+
47
+ ```bash
48
+ yass watch
49
+ ```
50
+
51
+ ## Layouts
52
+
53
+ Layouts live in `layouts/` and will be applied to files with matching names. The `content` variable contains the data to render in the layout.
54
+
55
+ *layouts/page.html.liquid*
56
+
57
+ ```html
58
+ <!DOCTYPE html>
59
+ <html lang="en">
60
+ <head>
61
+ <title>{{ page.title }}</title>
62
+ </head>
63
+ <body>{{ content }}</body>
64
+ </html>
65
+ ```
66
+
67
+ This template will be applied to files with names like `foo.page.html` and `foo.page.html.liquid`. The `.page` part of the name will be removed from the final file.
68
+
69
+ Since Markdown files (`foo.page.md`, `foo.page.md.liquid`) are converted to `.html` files, they'll also use `.html` layouts.
70
+
71
+ ## Templates
72
+
73
+ Templates live in `templates/` and can be used in any `.liquid` files.
74
+
75
+ *templates/greeting.liquid*
76
+
77
+ ```html
78
+ <p>Hi, my name is {{ name }}</p>
79
+ ```
80
+
81
+ Render the above template with `{% render "greeting", name: "Pleck" %}`.
82
+
83
+ NOTE: Liquid is pretty strict about template filenames. They must match `^[a-zA-Z0-9_]\.liquid$`.
84
+
85
+ ## Liquid variables
86
+
87
+ ### page
88
+
89
+ An object representing the current page. Properties:
90
+
91
+ * `title` A titleized version of the filename (e.g. *My File* from *my-file.html*)
92
+ * `url` URL path to the file (note that *index.html* stripped unless the `--local` option is used)
93
+ * `path` Same as `url` except *index.html* is never stripped
94
+ * `dirname` Directory file is in (e.g. *foo/bar* from *foo/bar/zorp.html*)
95
+ * `filename` Name of file (e.g. *zorp.html* from *foo/bar/zorp.html*)
96
+ * `extname` File extension (e.g. *.html* from *foo/bar/zorp.html*)
97
+ * `src_path` Path with the original filename (e.g. *foo/index.md.liquid*)
98
+
99
+ ### files
100
+
101
+ Any array of all files that will be written `dist/`. Same properties as `page`.
102
+
103
+ ## Liquid filters
104
+
105
+ ### relative_to
106
+
107
+ Modifies a path to be relative to another path. Useful in layouts and template that need to refer to another file.
108
+
109
+ ```html
110
+ <script src="{{ "assets/main.js" | relative_to: page.path }}"</script>
111
+ ```
112
+
113
+ ### match
114
+
115
+ Returns true if the string matches the regex.
116
+
117
+ ```liquid
118
+ {% assign is_asset = page.path | match: "\.(css|js|jpe?g)$"
119
+ ```
120
+
121
+ ## Liquid tags
122
+
123
+ ### highlight
124
+
125
+ Converts the given code into something useable by [Highlight.js](https://highlightjs.org/).
126
+
127
+ ```liquid
128
+ {% highlight ruby %}
129
+ puts "Yass!"
130
+ {% endhighlight %}
131
+ ```
132
+
133
+ 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.
134
+
135
+ ## Legal
44
136
 
45
137
  MIT License. See LICENSE for details.
46
138
 
data/bin/yass CHANGED
@@ -14,6 +14,10 @@ when :init
14
14
  config = Yass::CLI::Helpers.get_opts!
15
15
  retval = Yass::CLI::Runner.init(config, argv: ARGV)
16
16
  exit retval
17
+ when :watch
18
+ config = Yass::CLI::Helpers.get_opts!
19
+ retval = Yass::CLI::Runner.watch(config, argv: ARGV)
20
+ exit retval
17
21
  else
18
22
  Yass::CLI::Helpers.help!
19
23
  end
@@ -33,7 +33,7 @@ module Yass
33
33
  def self.option_parser(config)
34
34
  OptionParser.new { |opts|
35
35
  opts.banner = %(
36
- Yet Another Static Site (generator)
36
+ Yet Another Static Site (generator) v#{VERSION}
37
37
 
38
38
  yass <command> [options] [path/to/dir]
39
39
 
@@ -41,13 +41,18 @@ yass <command> [options] [path/to/dir]
41
41
  yass build
42
42
  yass build path/to/dir
43
43
 
44
+ Auto-build when files change:
45
+ yass watch
46
+ yass watch path/to/dir
47
+
44
48
  Create a new site:
45
49
  yass init <path/to/dir>
46
50
 
47
51
  Options:
48
52
  ).strip
49
- opts.on("--local", "Build in local mode (with links to /index.html's)") { |l| config.local = true }
50
- opts.on("--debug", "Print stack traces") { |l| config.debug = true }
53
+ opts.on("--clean", "Remove unknown files from dist/ when bulding") { config.clean = true }
54
+ opts.on("--local", "Build in local mode (with links to /index.html's)") { config.local = true }
55
+ opts.on("--debug", "Print stack traces") { config.debug = true }
51
56
  opts.on("-h", "--help", "Prints this help") { config.stdout.puts opts; exit }
52
57
  }
53
58
  end
@@ -59,6 +64,7 @@ yass <command> [options] [path/to/dir]
59
64
  layouts: "layouts",
60
65
  templates: "templates",
61
66
  dest: "dist",
67
+ clean: false,
62
68
  local: false,
63
69
  stdin: $stdin,
64
70
  stdout: $stdout,
@@ -3,7 +3,7 @@ require 'fileutils'
3
3
  module Yass
4
4
  module CLI
5
5
  module Runner
6
- INIT_DIR = Pathname.new(File.expand_path(File.join("..", "..", "..", "template"), __FILE__))
6
+ INIT_DIR = Pathname.new(File.expand_path(File.join("..", "..", "..", "..", "site-template"), __FILE__))
7
7
 
8
8
  def self.build(config, argv:)
9
9
  args = Helpers.get_args!(argv, max: 1)
@@ -33,6 +33,19 @@ module Yass
33
33
  config.stderr.puts "#{e.class.name}: #{e.message}"
34
34
  return 1
35
35
  end
36
+
37
+ def self.watch(config, argv:)
38
+ config.stdout.puts "Watching for changes..."
39
+ watcher = Filewatcher.new([config.src_dir, config.layout_dir, config.template_dir].map(&:to_s))
40
+ yield watcher if block_given?
41
+ watcher.watch do |changes|
42
+ files = changes.map { |f, _| Pathname.new(f).relative_path_from(config.root).to_s }
43
+ config.stdout.puts "Building #{files.join ", "}"
44
+ config.clear_cache!
45
+ Yass::CLI::Runner.build(config, argv: argv)
46
+ end
47
+ return 0
48
+ end
36
49
  end
37
50
  end
38
51
  end
data/lib/yass/config.rb CHANGED
@@ -1,10 +1,15 @@
1
1
  module Yass
2
- Config = Struct.new(:root, :src, :dest, :layouts, :templates, :local, :stdin, :stdout, :stderr, :debug, keyword_init: true) do
2
+ Config = Struct.new(:root, :src, :dest, :layouts, :templates, :clean, :local, :stdin, :stdout, :stderr, :debug, keyword_init: true) do
3
3
  def src_dir = root.join src
4
4
  def dest_dir = root.join dest
5
5
  def template_dir = root.join templates
6
6
  def layout_dir = root.join layouts
7
7
 
8
+ def clear_cache!
9
+ @sources = nil
10
+ @layout_cache = nil
11
+ end
12
+
8
13
  def layout_cache
9
14
  @layout_cache ||= Dir[layout_dir.join("*.liquid")].each_with_object({}) do |path, acc|
10
15
  path = Pathname.new(path)
@@ -25,7 +30,7 @@ module Yass
25
30
  env.error_mode = :strict
26
31
  env.file_system = Liquid::LocalFileSystem.new(template_dir.to_s, "%s.liquid")
27
32
  env.register_filter LiquidFilters
28
- env.register_tag 'highlight', LiquidHighlightTag
33
+ env.register_tag 'highlight', LiquidTags::Highlight
29
34
  end
30
35
  end
31
36
  end
@@ -19,6 +19,7 @@ module Yass
19
19
  FileUtils.cp(source.path, outfile)
20
20
  end
21
21
  end
22
+ clean if config.clean
22
23
  end
23
24
 
24
25
  private
@@ -36,10 +37,16 @@ module Yass
36
37
  return outfile, content if source.layout.nil?
37
38
 
38
39
  page = source.layout.render(source) { content }
39
- return outfile.dirname.join(source.rendered_filename), page
40
+ return outfile.dirname.join(source.dest_path.basename), page
40
41
  end
41
42
  end
42
43
 
44
+ 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 }
47
+ (actual_files - expected_files).each { |f| FileUtils.rm f }
48
+ end
49
+
43
50
  def dest_dirs
44
51
  config.sources.map { |s| config.dest_dir.join(s.relative_path).dirname }.uniq
45
52
  end
@@ -6,5 +6,7 @@ module Yass
6
6
  updirs = in_root ? [] : to.dirname.to_s.split("/").map { ".." }
7
7
  Pathname.new([*updirs, url].join("/")).to_s
8
8
  end
9
+
10
+ def match(str, regex) = Regexp.new(regex).match? str
9
11
  end
10
12
  end
@@ -0,0 +1,16 @@
1
+ module Yass
2
+ module LiquidTags
3
+ class Highlight < Liquid::Block
4
+ attr_reader :lang
5
+
6
+ def initialize(_tag_name, lang, _tokens)
7
+ super
8
+ @lang = lang.strip
9
+ end
10
+
11
+ def render(_context)
12
+ %(<pre><code class="language-#{lang}">#{super}</code></pre>)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -13,7 +13,7 @@ module Yass
13
13
  end
14
14
 
15
15
  def render(source)
16
- vars = { "page" => page_attrs(source), "files" => files_attrs(source.config.sources) }
16
+ vars = { "page" => file_attrs(source), "files" => files_attrs(source.config.sources) }
17
17
  vars["content"] = yield if block_given?
18
18
  content = @template.render(vars, { strict_variables: true, strict_filters: true })
19
19
  if @template.errors.any?
@@ -25,25 +25,18 @@ module Yass
25
25
 
26
26
  private
27
27
 
28
- def page_attrs(source)
28
+ def file_attrs(source)
29
29
  {
30
30
  "title" => source.title,
31
31
  "url" => source.url.to_s,
32
- "path" => source.relative_path.dirname.join(source.rendered_filename).to_s,
32
+ "path" => source.dest_path.to_s,
33
+ "src_path" => source.relative_path.to_s,
34
+ "dirname" => source.relative_path.dirname.to_s,
35
+ "filename" => source.dest_path.basename.to_s,
36
+ "extname" => source.dest_path.basename.extname,
33
37
  }
34
38
  end
35
39
 
36
- def files_attrs(sources)
37
- sources.map do |source|
38
- {
39
- "url" => source.url.to_s,
40
- "path" => source.relative_path.dirname.join(source.rendered_filename).to_s,
41
- "dirname" => source.relative_path.dirname.to_s,
42
- "filename" => source.rendered_filename,
43
- "extname" => source.rendered_filename[/\.[^.]+$/],
44
- "title" => source.title,
45
- }
46
- end
47
- end
40
+ def files_attrs(sources) = sources.map { |s| file_attrs s }
48
41
  end
49
42
  end
data/lib/yass/source.rb CHANGED
@@ -1,44 +1,42 @@
1
1
  module Yass
2
2
  class Source
3
3
  EXT_CONVERSIONS = {"md" => "html"}.freeze
4
- attr_reader :config, :path, :layout, :relative_path, :rendered_filename
4
+ attr_reader :config, :path, :layout, :relative_path, :dest_path
5
5
 
6
6
  def initialize(config, path)
7
7
  @config = config
8
8
  @path = path
9
9
  @relative_path = path.relative_path_from config.src_dir
10
- @layout, @rendered_filename = parse_name
10
+ dest_filename, @layout= parse_name
11
+ @dest_path = relative_path.dirname.join(dest_filename)
11
12
  end
12
13
 
13
- def url
14
- url = relative_path.dirname.join(rendered_filename)
15
- index? && !config.local ? url.dirname : url
16
- end
14
+ def url = index? && !config.local ? dest_path.dirname : dest_path
17
15
 
18
16
  def title
19
- fname = rendered_filename.sub(/\..+$/, "").to_s
17
+ fname = dest_path.basename.sub(/\..+$/, "").to_s
20
18
  fname = relative_path.dirname.basename.to_s if fname == "index"
21
19
  fname = "Home" if fname == "."
22
20
  fname.sub(/[_-]+/, " ").split(/ +/).map(&:capitalize).join(" ")
23
21
  end
24
22
 
25
- def dynamic? = !!(/\.(liquid|md)(\..*)?$/ =~ path.basename.to_s || layout)
23
+ def dynamic? = !!(/\.(liquid|md)(\..+)?$/ =~ path.basename.to_s || layout)
26
24
 
27
- def index? = rendered_filename == "index.html"
25
+ def index? = dest_path.basename.to_s == "index.html"
28
26
 
29
27
  private
30
28
 
31
29
  def parse_name
32
30
  name, exts = path.basename.to_s.split(".", 2)
33
- return nil, name if exts.nil?
31
+ return name, nil if exts.nil?
34
32
 
35
33
  exts = exts.split(".").map { |x| EXT_CONVERSIONS[x] || x } - %w[liquid]
36
- return nil, "#{name}.#{exts.join "."}" if exts.size < 2
34
+ return "#{name}.#{exts.join "."}", nil if exts.size < 2
37
35
 
38
36
  layout = config.layout_cache["#{exts[-2..].join(".")}"]
39
37
  exts.delete_at(-2) if layout
40
38
 
41
- return layout, "#{name}.#{exts.join "."}"
39
+ return "#{name}.#{exts.join "."}", layout
42
40
  end
43
41
  end
44
42
  end
data/lib/yass/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yass
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
data/lib/yass.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'pathname'
2
+ require 'filewatcher'
2
3
  require 'kramdown'
3
4
  require 'liquid'
4
5
 
@@ -7,7 +8,7 @@ module Yass
7
8
  autoload :Config, 'yass/config'
8
9
  autoload :Generator, 'yass/generator'
9
10
  autoload :LiquidFilters, 'yass/liquid_filters'
10
- autoload :LiquidHighlightTag, 'yass/liquid_highlight_tag'
11
+ autoload :LiquidTags, 'yass/liquid_tags'
11
12
  autoload :LiquidTemplate, 'yass/liquid_template'
12
13
  autoload :Source, 'yass/source'
13
14
  autoload :VERSION, 'yass/version'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.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-08 00:00:00.000000000 Z
11
+ date: 2025-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: filewatcher
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: kramdown
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -47,12 +61,6 @@ extra_rdoc_files: []
47
61
  files:
48
62
  - README.md
49
63
  - bin/yass
50
- - lib/template/layouts/default.html.liquid
51
- - lib/template/site/assets/highlight-default.css
52
- - lib/template/site/assets/highlight.min.js
53
- - lib/template/site/index.default.html.liquid
54
- - lib/template/templates/css_links.liquid
55
- - lib/template/templates/js_scripts.liquid
56
64
  - lib/yass.rb
57
65
  - lib/yass/cli.rb
58
66
  - lib/yass/cli/helpers.rb
@@ -60,10 +68,16 @@ files:
60
68
  - lib/yass/config.rb
61
69
  - lib/yass/generator.rb
62
70
  - lib/yass/liquid_filters.rb
63
- - lib/yass/liquid_highlight_tag.rb
71
+ - lib/yass/liquid_tags.rb
64
72
  - lib/yass/liquid_template.rb
65
73
  - lib/yass/source.rb
66
74
  - lib/yass/version.rb
75
+ - site-template/layouts/default.html.liquid
76
+ - site-template/site/assets/highlight-default.css
77
+ - site-template/site/assets/highlight.min.js
78
+ - site-template/site/index.default.html.liquid
79
+ - site-template/templates/css_links.liquid
80
+ - site-template/templates/js_scripts.liquid
67
81
  homepage: https://github.com/jhollinger/yass
68
82
  licenses:
69
83
  - MIT
@@ -1,14 +0,0 @@
1
- module Yass
2
- class LiquidHighlightTag < Liquid::Block
3
- attr_reader :lang
4
-
5
- def initialize(_tag_name, lang, _tokens)
6
- super
7
- @lang = lang.strip
8
- end
9
-
10
- def render(_context)
11
- %(<pre><code class="language-#{lang}">#{super}</code></pre>)
12
- end
13
- end
14
- end