yass 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ <h1>Home</h1>
@@ -0,0 +1,4 @@
1
+ {% assign css_files = files | where: "extname", ".css" -%}
2
+ {% for file in css_files %}
3
+ <link rel="stylesheet" href="{{ file.url | relative_to: page.url }}">
4
+ {% endfor %}
@@ -0,0 +1,4 @@
1
+ {% assign js_files = files | where: "extname", ".js" -%}
2
+ {% for file in js_files %}
3
+ <script src="{{ file.url | relative_to: page.url }}"></script>
4
+ {% endfor %}
@@ -0,0 +1,71 @@
1
+ require 'optparse'
2
+
3
+ module Yass
4
+ module CLI
5
+ module Helpers
6
+ def self.get_cmd(argv)
7
+ argv[0].to_s.to_sym
8
+ end
9
+
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
17
+ end
18
+
19
+ def self.get_opts!
20
+ config = default_config
21
+ parser = option_parser config
22
+ parser.parse!
23
+ config
24
+ end
25
+
26
+ def self.help!
27
+ config = default_config
28
+ parser = option_parser config
29
+ config.stdout.puts parser.help
30
+ exit 1
31
+ end
32
+
33
+ def self.option_parser(config)
34
+ OptionParser.new { |opts|
35
+ opts.banner = %(
36
+ Yet Another Static Site (generator)
37
+
38
+ yass <command> [options] [path/to/dir]
39
+
40
+ Build the site:
41
+ yass build
42
+ yass build path/to/dir
43
+
44
+ Create a new site:
45
+ yass init <path/to/dir>
46
+
47
+ Options:
48
+ ).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 }
51
+ opts.on("-h", "--help", "Prints this help") { config.stdout.puts opts; exit }
52
+ }
53
+ end
54
+
55
+ def self.default_config
56
+ Config.new({
57
+ root: Pathname.new(Dir.pwd),
58
+ src: "site",
59
+ layouts: "layouts",
60
+ templates: "templates",
61
+ dest: "dist",
62
+ local: false,
63
+ stdin: $stdin,
64
+ stdout: $stdout,
65
+ stderr: $stderr,
66
+ debug: false,
67
+ })
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,38 @@
1
+ require 'fileutils'
2
+
3
+ module Yass
4
+ module CLI
5
+ module Runner
6
+ INIT_DIR = Pathname.new(File.expand_path(File.join("..", "..", "..", "template"), __FILE__))
7
+
8
+ def self.build(config, argv:)
9
+ args = Helpers.get_args!(argv, max: 1)
10
+ config.root = Pathname.new(args[0] || Dir.pwd)
11
+ Generator.new(config).generate!
12
+ return 0
13
+ rescue => e
14
+ raise e if config.debug
15
+ config.stderr.puts "#{e.class.name}: #{e.message}"
16
+ return 1
17
+ end
18
+
19
+ def self.init(config, argv:)
20
+ args = Helpers.get_args!(argv, max: 1)
21
+ config.root = Pathname.new(args[0] || Dir.pwd)
22
+
23
+ Dir[INIT_DIR.join("**/*.*")].each do |path|
24
+ dest = config.root.join Pathname.new(path).relative_path_from(INIT_DIR)
25
+ config.stdout.puts "Creating #{dest}"
26
+ FileUtils.mkdir_p dest.dirname unless dest.dirname.exist?
27
+ FileUtils.cp(path, dest) unless dest.exist?
28
+ end
29
+
30
+ return 0
31
+ rescue => e
32
+ raise e if config.debug
33
+ config.stderr.puts "#{e.class.name}: #{e.message}"
34
+ return 1
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/yass/cli.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Yass
2
+ module CLI
3
+ autoload :Helpers, 'yass/cli/helpers'
4
+ autoload :Runner, 'yass/cli/runner'
5
+ end
6
+ end
@@ -0,0 +1,32 @@
1
+ module Yass
2
+ Config = Struct.new(:root, :src, :dest, :layouts, :templates, :local, :stdin, :stdout, :stderr, :debug, keyword_init: true) do
3
+ def src_dir = root.join src
4
+ def dest_dir = root.join dest
5
+ def template_dir = root.join templates
6
+ def layout_dir = root.join layouts
7
+
8
+ def layout_cache
9
+ @layout_cache ||= Dir[layout_dir.join("*.liquid")].each_with_object({}) do |path, acc|
10
+ path = Pathname.new(path)
11
+ name = path.basename.to_s
12
+ acc[name.sub(/\.liquid$/, "")] = LiquidTemplate.compile(self, name, path.read)
13
+ end.freeze
14
+ end
15
+
16
+ def sources
17
+ @sources ||= Dir[src_dir.join("**", "*")]
18
+ .reject { |path| Dir.exist? path }
19
+ .map { |path| Pathname.new path }
20
+ .map { |path| Source.new(self, path) }
21
+ end
22
+
23
+ def liquid_env
24
+ @liquid_env ||= Liquid::Environment.build do |env|
25
+ env.error_mode = :strict
26
+ env.file_system = Liquid::LocalFileSystem.new(template_dir.to_s, "%s.liquid")
27
+ env.register_filter LiquidFilters
28
+ env.register_tag 'highlight', LiquidHighlightTag
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ require 'fileutils'
2
+
3
+ module Yass
4
+ class Generator
5
+ attr_reader :config
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def generate!
12
+ dest_dirs.each { |dir| FileUtils.mkdir_p dir }
13
+ config.sources.each do |source|
14
+ outfile = config.dest_dir.join(source.relative_path)
15
+ if source.dynamic?
16
+ outfile, content = generate(source, outfile)
17
+ outfile.write content
18
+ else
19
+ FileUtils.cp(source.path, outfile)
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def generate(source, outfile, content = source.path.read)
27
+ case outfile.extname
28
+ when ".md"
29
+ content = Kramdown::Document.new(content).to_html
30
+ return generate(source, outfile.sub(/\.md$/, ".html"), content)
31
+ when ".liquid"
32
+ template = LiquidTemplate.compile(config, source.relative_path, content)
33
+ content = template.render(source)
34
+ return generate(source, outfile.sub(/\.liquid$/, ""), content)
35
+ else
36
+ return outfile, content if source.layout.nil?
37
+
38
+ page = source.layout.render(source) { content }
39
+ return outfile.dirname.join(source.rendered_filename), page
40
+ end
41
+ end
42
+
43
+ def dest_dirs
44
+ config.sources.map { |s| config.dest_dir.join(s.relative_path).dirname }.uniq
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,10 @@
1
+ module Yass
2
+ module LiquidFilters
3
+ def relative_to(url, to)
4
+ url, to = Pathname.new(url), Pathname.new(to)
5
+ in_root = to.dirname.to_s == "."
6
+ updirs = in_root ? [] : to.dirname.to_s.split("/").map { ".." }
7
+ Pathname.new([*updirs, url].join("/")).to_s
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,49 @@
1
+ module Yass
2
+ class LiquidTemplate
3
+ def self.compile(config, name, src)
4
+ template = Liquid::Template.parse(src, environment: config.liquid_env)
5
+ new(name, template)
6
+ end
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(name, template)
11
+ @name = name
12
+ @template = template
13
+ end
14
+
15
+ def render(source)
16
+ vars = { "page" => page_attrs(source), "files" => files_attrs(source.config.sources) }
17
+ vars["content"] = yield if block_given?
18
+ content = @template.render(vars, { strict_variables: true, strict_filters: true })
19
+ if @template.errors.any?
20
+ source.config.stderr.puts "Errors found in #{name}:"
21
+ source.config.stderr.puts @template.errors.map { |e| " #{e}" }.join("\n")
22
+ end
23
+ content
24
+ end
25
+
26
+ private
27
+
28
+ def page_attrs(source)
29
+ {
30
+ "title" => source.title,
31
+ "url" => source.url.to_s,
32
+ "path" => source.relative_path.dirname.join(source.rendered_filename).to_s,
33
+ }
34
+ end
35
+
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
48
+ end
49
+ end
@@ -0,0 +1,44 @@
1
+ module Yass
2
+ class Source
3
+ EXT_CONVERSIONS = {"md" => "html"}.freeze
4
+ attr_reader :config, :path, :layout, :relative_path, :rendered_filename
5
+
6
+ def initialize(config, path)
7
+ @config = config
8
+ @path = path
9
+ @relative_path = path.relative_path_from config.src_dir
10
+ @layout, @rendered_filename = parse_name
11
+ end
12
+
13
+ def url
14
+ url = relative_path.dirname.join(rendered_filename)
15
+ index? && !config.local ? url.dirname : url
16
+ end
17
+
18
+ def title
19
+ fname = rendered_filename.sub(/\..+$/, "").to_s
20
+ fname = relative_path.dirname.basename.to_s if fname == "index"
21
+ fname = "Home" if fname == "."
22
+ fname.sub(/[_-]+/, " ").split(/ +/).map(&:capitalize).join(" ")
23
+ end
24
+
25
+ def dynamic? = !!(/\.(liquid|md)(\..*)?$/ =~ path.basename.to_s || layout)
26
+
27
+ def index? = rendered_filename == "index.html"
28
+
29
+ private
30
+
31
+ def parse_name
32
+ name, exts = path.basename.to_s.split(".", 2)
33
+ return nil, name if exts.nil?
34
+
35
+ exts = exts.split(".").map { |x| EXT_CONVERSIONS[x] || x } - %w[liquid]
36
+ return nil, "#{name}.#{exts.join "."}" if exts.size < 2
37
+
38
+ layout = config.layout_cache["#{exts[-2..].join(".")}"]
39
+ exts.delete_at(-2) if layout
40
+
41
+ return layout, "#{name}.#{exts.join "."}"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Yass
2
+ VERSION = "0.0.1".freeze
3
+ end
data/lib/yass.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'pathname'
2
+ require 'kramdown'
3
+ require 'liquid'
4
+
5
+ module Yass
6
+ autoload :CLI, 'yass/cli'
7
+ autoload :Config, 'yass/config'
8
+ autoload :Generator, 'yass/generator'
9
+ autoload :LiquidFilters, 'yass/liquid_filters'
10
+ autoload :LiquidHighlightTag, 'yass/liquid_highlight_tag'
11
+ autoload :LiquidTemplate, 'yass/liquid_template'
12
+ autoload :Source, 'yass/source'
13
+ autoload :VERSION, 'yass/version'
14
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yass
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jordan Hollinger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kramdown
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'
27
+ - !ruby/object:Gem::Dependency
28
+ name: liquid
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ description: A dead-simple static site generator
42
+ email: jordan.hollinger@gmail.com
43
+ executables:
44
+ - yass
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - README.md
49
+ - 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
+ - lib/yass.rb
57
+ - lib/yass/cli.rb
58
+ - lib/yass/cli/helpers.rb
59
+ - lib/yass/cli/runner.rb
60
+ - lib/yass/config.rb
61
+ - lib/yass/generator.rb
62
+ - lib/yass/liquid_filters.rb
63
+ - lib/yass/liquid_highlight_tag.rb
64
+ - lib/yass/liquid_template.rb
65
+ - lib/yass/source.rb
66
+ - lib/yass/version.rb
67
+ homepage: https://github.com/jhollinger/yass
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 3.0.0
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 3.4.19
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Yet Another Static Site (generator)
90
+ test_files: []