charsi 0.1.4 → 0.1.5

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: 383a30056fa0b9509776f3960cc454cdaa00c0b8b590b361cecf6bfd4cd98703
4
- data.tar.gz: '03954d083f4e40062a5436ac8f3fc26a1a2c6905c2288019df0f5393863ab4f1'
3
+ metadata.gz: e4894331787c5775e21343e7942bffc421d433638749553e57922234f56fba97
4
+ data.tar.gz: 1b3346e7494836267395d5d66ae8ad5bed4cbeaf2124d03e81257152a580b035
5
5
  SHA512:
6
- metadata.gz: 1853db1c935c50e68d604fa755a8ea2b2775ee333810068255b23f46185be5866557e8560672d4ade6aa764f906e52e7d4ecf6da06f1a71cce6fb152a4589043
7
- data.tar.gz: e2ed41bff4f042489e408e0f65a73a4663f0edf00a3454cfe2dd114770fba54556bb31a7afcfae0f4becd9a8dc97de37e86aff150dbf9ee538677654c19c36fe
6
+ metadata.gz: 5caa649097f056fda5ac9ed8ed9e282320e638d9db2723cc76619e51d7d575d7c8dcdcea6373abf8fc6fe7148b33097e276856e0f5a719d46e36c446f252522f
7
+ data.tar.gz: 41283471f53d8495fdd907f325ea08cebb0f0ac28bf6ade7d861a838655b1a2a6e0f67f446c69b7fb981856c65660b2266a3ffde54f9ad9e0c502cde0afdcdc7
data/Gemfile CHANGED
@@ -5,8 +5,8 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in charsi.gemspec
6
6
  gemspec
7
7
 
8
- gem 'rake', '~> 13.0'
9
- gem 'terser', '~> 1.2'
8
+ gem 'rake', '~> 13.0'
9
+ gem 'minitest', '~> 5.0', group: :development
10
10
  gem 'tilt', '~> 2.6'
11
11
  gem 'tailwindcss-ruby', '~> 4.1'
12
12
  gem 'filewatcher', '~> 3.0'
data/Gemfile.lock CHANGED
@@ -1,33 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- charsi (0.1.3)
4
+ charsi (0.1.5)
5
5
  filewatcher (~> 3.0)
6
6
  logger (~> 1.6)
7
7
  tailwindcss-ruby (~> 4.1)
8
- terser (~> 1.2)
9
8
  tilt (~> 2.6)
10
9
  webrick (~> 1.9)
11
10
 
12
11
  GEM
13
12
  remote: https://rubygems.org/
14
13
  specs:
15
- execjs (2.10.0)
16
14
  filewatcher (3.0.1)
17
15
  logger (~> 1.7)
18
16
  module_methods (~> 1.0)
19
17
  logger (1.7.0)
18
+ minitest (5.27.0)
20
19
  module_methods (1.0.0)
21
20
  rake (13.3.1)
22
21
  tailwindcss-ruby (4.2.1)
23
22
  tailwindcss-ruby (4.2.1-aarch64-linux-gnu)
24
23
  tailwindcss-ruby (4.2.1-aarch64-linux-musl)
25
24
  tailwindcss-ruby (4.2.1-arm64-darwin)
25
+ tailwindcss-ruby (4.2.1-x64-mingw-ucrt)
26
26
  tailwindcss-ruby (4.2.1-x86_64-darwin)
27
27
  tailwindcss-ruby (4.2.1-x86_64-linux-gnu)
28
28
  tailwindcss-ruby (4.2.1-x86_64-linux-musl)
29
- terser (1.2.6)
30
- execjs (>= 0.3.0, < 3)
31
29
  tilt (2.7.0)
32
30
  webrick (1.9.2)
33
31
 
@@ -36,6 +34,7 @@ PLATFORMS
36
34
  aarch64-linux-musl
37
35
  arm64-darwin
38
36
  ruby
37
+ x64-mingw-ucrt
39
38
  x86_64-darwin
40
39
  x86_64-linux-gnu
41
40
  x86_64-linux-musl
@@ -43,28 +42,28 @@ PLATFORMS
43
42
  DEPENDENCIES
44
43
  charsi!
45
44
  filewatcher (~> 3.0)
45
+ minitest (~> 5.0)
46
46
  rake (~> 13.0)
47
47
  tailwindcss-ruby (~> 4.1)
48
- terser (~> 1.2)
49
48
  tilt (~> 2.6)
50
49
 
51
50
  CHECKSUMS
52
- charsi (0.1.3)
53
- execjs (2.10.0) sha256=6bcb8be8f0052ff9d370b65d1c080f2406656e150452a0abdb185a133048450d
51
+ charsi (0.1.5)
54
52
  filewatcher (3.0.1) sha256=b0f51e568cf112f72392053ae5ff5afa267592489091ee9f93c20fc275597f5a
55
53
  logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
54
+ minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5
56
55
  module_methods (1.0.0) sha256=92f28a9254b8c1a7f4e68aa52242ecabdac3343ce41909aac3fcc3bf2ac8ec5e
57
56
  rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
58
57
  tailwindcss-ruby (4.2.1) sha256=95886a1e24b42d76792c787d34e47098b53cb3b5a6363845bca4486f52b2e66a
59
58
  tailwindcss-ruby (4.2.1-aarch64-linux-gnu) sha256=de457ddfc999c6bbbe1a59fbc11eb2168d619f6e0cb72d8d3334d372b331e36f
60
59
  tailwindcss-ruby (4.2.1-aarch64-linux-musl) sha256=e6ed27704263201f8366316354aa45f9016cc9378ce8fac46fbbe65fafd4da5e
61
60
  tailwindcss-ruby (4.2.1-arm64-darwin) sha256=bcf222fb8542cf5433925623e5e7b257897fbb8291a2350daae870a32f2eeb91
61
+ tailwindcss-ruby (4.2.1-x64-mingw-ucrt) sha256=607b948a63262391e35081d6f06b9f9757bb151461195423736249cae7b32c2c
62
62
  tailwindcss-ruby (4.2.1-x86_64-darwin) sha256=b737b84f80941628d03c703b31abb204151b9d0a494d58ed06fd8220a5162f1b
63
63
  tailwindcss-ruby (4.2.1-x86_64-linux-gnu) sha256=201d0e5e5d4aba52cae4ee4bd1acd497d2790c83e7f15da964aab8ec93876831
64
64
  tailwindcss-ruby (4.2.1-x86_64-linux-musl) sha256=79fa48ad51e533545f9fdbb04227e1342a65a42c2bd1314118b95473d5612007
65
- terser (1.2.6) sha256=6ddf00b93df7015b07e2b9b149e74cd70fa7aa4f0f89a15d9922a6ebd13f37ab
66
65
  tilt (2.7.0) sha256=0d5b9ba69f6a36490c64b0eee9f6e9aad517e20dcc848800a06eb116f08c6ab3
67
66
  webrick (1.9.2) sha256=beb4a15fc474defed24a3bda4ffd88a490d517c9e4e6118c3edce59e45864131
68
67
 
69
68
  BUNDLED WITH
70
- 4.0.3
69
+ 4.0.6
data/LICENSE.txt CHANGED
File without changes
data/README.md CHANGED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new(:test) do |test|
4
+ test.libs << 'lib'
5
+ test.pattern = 'test/**/*_test.rb'
6
+ end
7
+
8
+ task default: :test
data/bin/charsi CHANGED
File without changes
data/charsi.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'charsi'
3
- spec.version = '0.1.4'
3
+ spec.version = '0.1.5'
4
4
 
5
5
  spec.authors = ['Ryan Beasse']
6
6
  spec.email = ['me@ryanbeasse.com']
@@ -18,16 +18,17 @@ Gem::Specification.new do |spec|
18
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
19
  spec.files = Dir.chdir(__dir__) do
20
20
  `git ls-files -z`.split("\x0").reject do |f|
21
- (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
21
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[test/ .git .github .devcontainer])
22
22
  end
23
23
  end
24
24
 
25
25
  spec.executables << 'charsi'
26
26
 
27
- spec.add_dependency 'terser', '~> 1.2'
28
27
  spec.add_dependency 'tilt', '~> 2.6'
29
28
  spec.add_dependency 'tailwindcss-ruby', '~> 4.1'
30
29
  spec.add_dependency 'filewatcher', '~> 3.0'
31
30
  spec.add_dependency 'logger', '~> 1.6'
32
31
  spec.add_dependency 'webrick', '~> 1.9'
32
+
33
+ spec.add_development_dependency 'minitest', '~> 5.0'
33
34
  end
data/lib/charsi/app.rb CHANGED
@@ -15,12 +15,12 @@ module Charsi
15
15
 
16
16
  protected
17
17
 
18
- def stylesheet_tag(asset)
19
- "<link rel='stylesheet' href='assets/css/#{asset}?#{@cache_slug}'>"
18
+ def stylesheet_tag(asset, **attributes)
19
+ "<link rel='stylesheet' href='assets/css/#{asset}?#{@cache_slug}'#{html_attributes(attributes)}>"
20
20
  end
21
21
 
22
- def javascript_tag(asset)
23
- "<script src='assets/javascript/#{asset}?#{@cache_slug}'></script>"
22
+ def javascript_tag(asset, **attributes)
23
+ "<script src='#{javascript_src(asset)}'#{html_attributes(attributes)}></script>"
24
24
  end
25
25
 
26
26
  def render_partial(partial_name, **locals)
@@ -32,6 +32,18 @@ module Charsi
32
32
 
33
33
  private
34
34
 
35
+ def javascript_src(asset)
36
+ if asset.is_a?(Symbol)
37
+ "assets/vendor/#{asset}.js?#{@cache_slug}"
38
+ else
39
+ "assets/javascript/#{asset}?#{@cache_slug}"
40
+ end
41
+ end
42
+
43
+ def html_attributes(attributes)
44
+ attributes.map { |attribute, value| " #{attribute}='#{value}'" }.join
45
+ end
46
+
35
47
  def load_helpers
36
48
  helpers_path = @config.path(:helpers_dir)
37
49
 
data/lib/charsi/asset.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  module Charsi
2
2
  # Itterates each assets, processes them, and copies them to the output directory.
3
- #
4
- # JavaScript and CSS files are minified.
5
3
  class Asset
4
+ UNPKG_BASE = 'https://unpkg.com/'.freeze
5
+
6
6
  def initialize(config)
7
7
  @config = config
8
8
  end
9
9
 
10
10
  def build
11
+ build_vendor
12
+
11
13
  assets_path = @config.path(:assets_dir, '**', '*.*')
12
-
14
+
13
15
  Dir.glob(assets_path).each do |asset|
14
- extension = File.extname(asset)
15
16
  destination_dir = @config.path(:output_dir, 'assets')
16
17
  destination_path = asset.sub(@config.path(:assets_dir), destination_dir)
17
18
 
18
- next process_javascript(asset, destination_path) if extension == '.js'
19
19
  next process_tailwind(asset, destination_path) if asset.include?('tailwind.css')
20
20
 
21
21
  Charsi::FileManagement.copy(asset, destination_path)
@@ -24,6 +24,20 @@ module Charsi
24
24
 
25
25
  private
26
26
 
27
+ def build_vendor
28
+ @config.vendor.each do |key, package_path|
29
+ cache_path = @config.path(:cache_dir, 'vendor', "#{key}.js")
30
+ output_path = @config.path(:output_dir, 'assets', 'vendor', "#{key}.js")
31
+
32
+ Charsi::FileManagement.cached(cache_path) do |path|
33
+ puts "[charsi] Downloading vendor: #{key}"
34
+ Charsi::FileManagement.download("#{UNPKG_BASE}#{package_path}", path)
35
+ end
36
+
37
+ Charsi::FileManagement.copy(cache_path, output_path)
38
+ end
39
+ end
40
+
27
41
  def process_tailwind(asset, destination_path)
28
42
  commands = [Tailwindcss::Ruby.executable]
29
43
  commands += ['-i', asset, '-o', destination_path, '--minify']
@@ -31,11 +45,5 @@ module Charsi
31
45
 
32
46
  system(*commands)
33
47
  end
34
-
35
- def process_javascript(asset, destination_path)
36
- processed_asset = Terser.compile(File.read(asset))
37
-
38
- Charsi::FileManagement.write(destination_path, processed_asset)
39
- end
40
48
  end
41
49
  end
File without changes
@@ -13,6 +13,10 @@ module Charsi
13
13
  File.join(Dir.pwd, config_path, *keys)
14
14
  end
15
15
 
16
+ def vendor
17
+ @config.fetch('vendor', {})
18
+ end
19
+
16
20
 
17
21
  private
18
22
 
data/lib/charsi/file.rb CHANGED
@@ -19,5 +19,15 @@ module Charsi
19
19
  FileUtils.rm_rf(output_dir) if Dir.exist?(output_dir)
20
20
  FileUtils.mkdir_p(output_dir)
21
21
  end
22
+
23
+ def self.download(url, destination)
24
+ write(destination, URI.open(url, &:read)) # rubocop:disable Security/Open
25
+ rescue OpenURI::HTTPError => error
26
+ raise "[charsi] Failed to download #{url} — #{error.message}"
27
+ end
28
+
29
+ def self.cached(path)
30
+ File.exist?(path) ? path : yield(path)
31
+ end
22
32
  end
23
33
  end
@@ -5,7 +5,7 @@ module Charsi
5
5
  templates_dir = File.join(__dir__, '../../templates', template)
6
6
  templates_glob = File.join(templates_dir, '**', '*.template')
7
7
 
8
- Dir.glob(templates_glob).each do |template|
8
+ Dir.glob(templates_glob, File::FNM_DOTMATCH).each do |template|
9
9
  output_path = template.delete_prefix(templates_dir)
10
10
  output_path = output_path.delete_suffix('.template')
11
11
  output_path = File.join(Dir.pwd, project, output_path)
data/lib/charsi/server.rb CHANGED
File without changes
File without changes
data/lib/charsi.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'erb'
2
2
  require 'fileutils'
3
+ require 'open-uri'
3
4
  require 'tilt'
4
- require 'terser'
5
5
  require 'tailwindcss/ruby'
6
6
  require 'yaml'
7
7
  require 'filewatcher'
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "<%= project_title %>",
3
+ "image": "mcr.microsoft.com/devcontainers/ruby:4",
4
+ "postCreateCommand": "bundle install",
5
+ "customizations": {
6
+ "vscode": {
7
+ "extensions": [
8
+ "shopify.ruby-lsp"
9
+ ]
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,102 @@
1
+ # <%= project_title %>
2
+
3
+ This is a [Charsi](https://github.com/rbeasse/charsi) static site. Charsi is a simple Ruby static site generator that compiles ERB views, processes Tailwind CSS, and copies assets to a build directory.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ bundle exec charsi build # build the site to _build/
9
+ bundle exec charsi build --watch # build and watch for changes
10
+ bundle exec charsi serve # build and serve at http://localhost:8000
11
+ bundle exec charsi serve --watch # serve with live rebuilding on changes
12
+ ```
13
+
14
+ ## Project structure
15
+
16
+ ```
17
+ layouts/ ERB layouts — default.erb wraps all views via yield
18
+ views/ ERB views — each .erb file becomes an .html page
19
+ _partial.erb Partials are prefixed with _ and not compiled to pages
20
+ assets/
21
+ css/ CSS files — tailwind.css is processed by the Tailwind binary
22
+ javascript/ JS files — copied as-is to _build/assets/javascript/
23
+ helpers/ Ruby files auto-loaded and mixed into the template context
24
+ config.yml Project configuration
25
+ tailwind.config.js Tailwind configuration — content paths are pre-configured
26
+ _build/ Build output — do not edit, regenerated on every build
27
+ .charsi/ Charsi cache (vendor downloads) — do not edit or commit
28
+ ```
29
+
30
+ ## Views and layouts
31
+
32
+ Views are ERB files in `views/`. Each becomes a page at the same name:
33
+ - `views/index.erb` → `_build/index.html`
34
+ - `views/about.erb` → `_build/about.html`
35
+
36
+ The default layout in `layouts/default.erb` wraps every view. Use `yield` where the view content should appear.
37
+
38
+ Partials live in `views/` prefixed with `_` and are rendered via `render_partial`:
39
+
40
+ ```erb
41
+ <%%= render_partial('header') %>
42
+ <%%= render_partial('card', title: 'Hello', body: 'World') %>
43
+ ```
44
+
45
+ Locals passed to `render_partial` are available as variables in the partial.
46
+
47
+ ## Coding style
48
+
49
+ - Write clear, readable code — use full descriptive names, avoid shorthand or single-letter variables
50
+ - No inline JavaScript or CSS — JS belongs in `assets/javascript/`, styles in `assets/css/`
51
+ - Use Tailwind classes for styling whenever possible — only write custom CSS when Tailwind cannot achieve it or when explicitly asked
52
+ - Keep views focused on structure — logic belongs in helpers or partials
53
+
54
+ ## Template helpers
55
+
56
+ These methods are available in all views and layouts:
57
+
58
+ ```erb
59
+ <%%= stylesheet_tag('tailwind.css') %>
60
+ <%%= stylesheet_tag('tailwind.css', media: 'print') %>
61
+
62
+ <%%= javascript_tag('app.js') %>
63
+ <%%= javascript_tag('app.js', type: 'module', defer: true) %>
64
+ <%%= javascript_tag(:stimulus) %> <%# references a vendor library by key %>
65
+ ```
66
+
67
+ ## Tailwind CSS
68
+
69
+ The `assets/css/tailwind.css` file is the Tailwind entry point. It is processed by the Tailwind binary and minified. Use Tailwind classes directly in ERB files — `tailwind.config.js` is already configured to scan `views/` and `layouts/`.
70
+
71
+ ## Vendor JS
72
+
73
+ Third-party JS libraries can be declared in `config.yml` under `vendor:`. Charsi downloads them from [unpkg.com](https://unpkg.com) and caches them in `.charsi/vendor/`. They are copied to `_build/assets/vendor/` on every build.
74
+
75
+ ```yaml
76
+ vendor:
77
+ stimulus: "@hotwired/stimulus/dist/stimulus.js"
78
+ alpine: "alpinejs/dist/cdn.js"
79
+ ```
80
+
81
+ Reference them in templates with a symbol:
82
+
83
+ ```erb
84
+ <%%= javascript_tag(:stimulus, type: 'module') %>
85
+ ```
86
+
87
+ ## Custom helpers
88
+
89
+ Any `.rb` file in `helpers/` is automatically required and its methods become available in all views and layouts. Define helper methods as module-level methods:
90
+
91
+ ```ruby
92
+ # helpers/format_helper.rb
93
+ def format_date(date)
94
+ date.strftime('%B %d, %Y')
95
+ end
96
+ ```
97
+
98
+ Then use them directly in ERB:
99
+
100
+ ```erb
101
+ <%%= format_date(Time.now) %>
102
+ ```
File without changes
File without changes
File without changes
@@ -1,5 +1,6 @@
1
1
  paths:
2
2
  output_dir: '_build'
3
+ cache_dir: '.charsi'
3
4
  layout_dir: 'layouts'
4
5
  assets_dir: 'assets'
5
6
  views_dir: 'views'
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: charsi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Beasse
@@ -9,20 +9,6 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: terser
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: '1.2'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - "~>"
24
- - !ruby/object:Gem::Version
25
- version: '1.2'
26
12
  - !ruby/object:Gem::Dependency
27
13
  name: tilt
28
14
  requirement: !ruby/object:Gem::Requirement
@@ -93,6 +79,20 @@ dependencies:
93
79
  - - "~>"
94
80
  - !ruby/object:Gem::Version
95
81
  version: '1.9'
82
+ - !ruby/object:Gem::Dependency
83
+ name: minitest
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '5.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '5.0'
96
96
  email:
97
97
  - me@ryanbeasse.com
98
98
  executables:
@@ -104,6 +104,7 @@ files:
104
104
  - Gemfile.lock
105
105
  - LICENSE.txt
106
106
  - README.md
107
+ - Rakefile
107
108
  - bin/charsi
108
109
  - charsi.gemspec
109
110
  - lib/charsi.rb
@@ -115,6 +116,8 @@ files:
115
116
  - lib/charsi/generator.rb
116
117
  - lib/charsi/server.rb
117
118
  - lib/charsi/template.rb
119
+ - templates/site/.devcontainer/devcontainer.json.template
120
+ - templates/site/CLAUDE.md.template
118
121
  - templates/site/Gemfile.template
119
122
  - templates/site/assets/css/tailwind.css.template
120
123
  - templates/site/assets/javascript/app.js.template
@@ -142,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
145
  - !ruby/object:Gem::Version
143
146
  version: '0'
144
147
  requirements: []
145
- rubygems_version: 4.0.3
148
+ rubygems_version: 4.0.6
146
149
  specification_version: 4
147
150
  summary: Simple static site generator.
148
151
  test_files: []