beachio-hammer 0.1.0.pre1 → 0.1.0.pre2

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: 6fbc6c05d882741fa94434691763470a2a8ae5cec91713e0b0fb9e4e0cd25bca
4
- data.tar.gz: 22394aa9fae0d7b44a53d511a94a7a02a052c6cab1af769f51601e4c55adf166
3
+ metadata.gz: 341e9e0b4490d2d81d9bde191b50a864433452053f9045abf61ce6bf4ef8b8b4
4
+ data.tar.gz: 68c2e73b72fef89934937920211fdb35ccdb224d6e02c4ccf75b993e43aa1d9e
5
5
  SHA512:
6
- metadata.gz: 8703bd2e45433905cdd2d503d70e7179d5aed28c35a6f2c32f1418dafd4267c80bd0cb6162531c18c61b0a426bd2f5a7f7d9d361a68f8caed04c414f375d9071
7
- data.tar.gz: 62021958be80b18b3bd59059dc339399ca80650d1d9ea0e07d4f908093fb21f0ac8a95981d848f9495bd556ce3718e63e799186f21a28881d985c0f686d2b292
6
+ metadata.gz: 6ddf7826fd3a196ab07e5678a3735d3f9aeb236174f6c3deba61fc3c0594174eae7314ded5585aeb8a84c95de6bf35c741f71746106ff61920fe677166dae312
7
+ data.tar.gz: 8c13c6e4cbc8c6c36453bdc0c3d0f393182d42e3521d310bf6771ffbdc4ce91e507dda1709521f61ca8caa9cf35537015db220a654374c659fc0b0ff6ef37435
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- beachio-hammer (0.1.0.pre1)
4
+ beachio-hammer (0.1.0.pre2)
5
5
  json (~> 2.7)
6
6
 
7
7
  GEM
data/PUBLISH.md CHANGED
@@ -10,8 +10,21 @@ bundle exec rspec
10
10
 
11
11
  ## Capture golden Build/ trees (macOS Swift CLI)
12
12
 
13
+ From repo root:
14
+
15
+ ```bash
16
+ ./gem/scripts/capture-goldens.sh
17
+ ```
18
+
19
+ Or manually:
20
+
13
21
  ```bash
14
- ./scripts/capture-goldens.sh
22
+ xcodebuild -project Hammer-Swift.xcodeproj -scheme hammer-cli -configuration Release -derivedDataPath ./build-derived build
23
+ ./build-derived/Build/Products/Release/hammer build \
24
+ --project "Test Projects/classic-fixture" --mode export --clean --quiet
25
+ ./build-derived/Build/Products/Release/hammer build \
26
+ --project "Test Projects/content-generation-test" --mode export --clean --quiet
27
+ git add -f "Test Projects/classic-fixture/Build" "Test Projects/content-generation-test/Build"
15
28
  ```
16
29
 
17
30
  ## Publish to RubyGems
@@ -25,10 +38,57 @@ gem build beachio-hammer.gemspec
25
38
  gem push beachio-hammer-*.gem
26
39
  ```
27
40
 
41
+ Prerelease pin for executor team: **`beachio-hammer` `0.1.0.pre2`**
42
+
43
+ ### 0.1.0.pre2 changes (Beachio / Linux fixes)
44
+
45
+ - Force UTF-8 text reads (`Hammer.read_text`) — fixes `invalid byte sequence in US-ASCII` on Render
46
+ - `require "date"` for content pipeline
47
+ - `find_file` skips directories (Swift parity)
48
+ - `resolve_output_path` returns empty when collection has no output pattern
49
+
28
50
  ## hammer-cloud integration
29
51
 
30
52
  Pin the published gem version in the executor Dockerfile:
31
53
 
32
54
  ```dockerfile
33
- RUN gem install beachio-hammer -v 0.1.0.pre1
55
+ RUN gem install beachio-hammer -v 0.1.0.pre2
34
56
  ```
57
+
58
+ Build step in the agent:
59
+
60
+ ```bash
61
+ hammer build --project "$WORKSPACE" --mode export --format json --clean
62
+ ```
63
+
64
+ ### CLI contract
65
+
66
+ | Flag | Default | Notes |
67
+ |------|---------|-------|
68
+ | `--project` | cwd (walk-up for markers) | Project root |
69
+ | `--output` | `<project>/Build` | Output directory |
70
+ | `--mode` | `export` | `normal`, `export`, `publish` |
71
+ | `--format` | `human` | `json` for agent parsing |
72
+ | `--clean` | off | Wipes Build/ before compile |
73
+
74
+ **Exit codes:** `0` success, `1` build errors, `2` config error, `3` internal.
75
+
76
+ **JSON stdout** (`--format json`):
77
+
78
+ ```json
79
+ {
80
+ "status": "success",
81
+ "stats": { "filesProcessed", "errors", "warnings", "durationMs", "buildSize" },
82
+ "errors": [{ "file", "message" }],
83
+ "warnings": [{ "file", "message" }]
84
+ }
85
+ ```
86
+
87
+ ### Parity fixtures
88
+
89
+ | Fixture | Path | Files |
90
+ |---------|------|-------|
91
+ | Classic | `Test Projects/classic-fixture` | 9 |
92
+ | Content | `Test Projects/content-generation-test` | 13 |
93
+
94
+ CI: `.github/workflows/gem-parity.yml` — macOS re-exports goldens, Linux runs `bundle exec rspec`.
data/exe/hammer CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ Encoding.default_external = Encoding::UTF_8
5
+ Encoding.default_internal = Encoding::UTF_8
6
+
4
7
  require "beachio-hammer"
5
8
 
6
9
  exit Hammer::CLI.run(ARGV)
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "date"
4
+ require "time"
5
+
3
6
  require_relative "hammer/version"
7
+ require_relative "hammer/io"
4
8
  require_relative "hammer/errors"
5
9
  require_relative "hammer/ignore"
6
10
  require_relative "hammer/tag_parser"
@@ -134,7 +134,7 @@ module Hammer
134
134
 
135
135
  case ext
136
136
  when ".html"
137
- content = File.read(src)
137
+ content = Hammer.read_text(src)
138
138
  if !@content_collections.empty? && content.include?("@loop") && content.include?("collections.")
139
139
  content = Content::PageGenerator.pre_process_collection_loops(
140
140
  content,
@@ -148,7 +148,7 @@ module Hammer
148
148
  FileUtils.mkdir_p(File.dirname(dest))
149
149
  File.write(dest, processed)
150
150
  when ".css"
151
- processed = css_parser.parse(File.read(src), relative_path: rel)
151
+ processed = css_parser.parse(Hammer.read_text(src), relative_path: rel)
152
152
  FileUtils.mkdir_p(File.dirname(dest))
153
153
  File.write(dest, processed)
154
154
  else
@@ -45,7 +45,7 @@ module Hammer
45
45
  end
46
46
 
47
47
  def self.load(path)
48
- data = JSON.parse(File.read(path))
48
+ data = JSON.parse(Hammer.read_text(path))
49
49
  collections = data.fetch("collections", {}).transform_values { |c| CollectionConfig.from_hash(c) }
50
50
  new(collections: collections, site_url: data["siteUrl"])
51
51
  end
@@ -28,7 +28,7 @@ module Hammer
28
28
 
29
29
  def date
30
30
  val = metadata["date"]
31
- return val if val.is_a?(Time) || val.is_a?(Date)
31
+ return val if val.is_a?(Time) || val.is_a?(::Date)
32
32
 
33
33
  self.class.parse_date(val.to_s) if val
34
34
  end
@@ -83,7 +83,7 @@ module Hammer
83
83
  value.map { |v| serialize_value(v) }
84
84
  when Hash
85
85
  value.transform_values { |v| serialize_value(v) }
86
- when Time, Date
86
+ when Time, ::Date
87
87
  value.utc.iso8601(3)
88
88
  else
89
89
  value
@@ -97,7 +97,7 @@ module Hammer
97
97
  when String then value
98
98
  when TrueClass, FalseClass then value.to_s
99
99
  when Numeric then value.to_s
100
- when Time, Date then value.to_s
100
+ when Time, ::Date then value.to_s
101
101
  when Document then value.slug
102
102
  else value.to_s
103
103
  end
@@ -33,7 +33,7 @@ module Hammer
33
33
  format = "medium" if format.empty? || format == "null"
34
34
 
35
35
  time = case date_val
36
- when Time, Date then date_val.to_time
36
+ when Time, ::Date then date_val.to_time
37
37
  when String then Document.parse_date(date_val)
38
38
  else nil
39
39
  end
@@ -59,6 +59,8 @@ module Hammer
59
59
 
60
60
  def resolve_output_path(doc, collection_config)
61
61
  pattern = collection_config.output_path_pattern
62
+ return "" if pattern.nil? || pattern.empty?
63
+
62
64
  slug_field = collection_config.slug&.dig("field") || "slug"
63
65
  slug = resolve_slug(doc, collection_config.slug)
64
66
  interpolate_output_path(pattern, slug, slug_field)
@@ -88,7 +90,7 @@ module Hammer
88
90
  end
89
91
 
90
92
  def generate_page(template_path, doc, output_path)
91
- template = File.read(template_path)
93
+ template = Hammer.read_text(template_path)
92
94
  site = { "title" => "My Site" }
93
95
  context = TemplateContext.new(
94
96
  site: site,
@@ -8,7 +8,7 @@ module Hammer
8
8
  end
9
9
 
10
10
  def parse_markdown_file(path)
11
- content = File.read(path)
11
+ content = Hammer.read_text(path)
12
12
  metadata, body = extract_front_matter(content)
13
13
  html_body = parse_markdown_body(body)
14
14
  collection = extract_collection(path)
@@ -22,7 +22,7 @@ module Hammer
22
22
  end
23
23
 
24
24
  def parse_yaml_file(path)
25
- metadata = parse_simple_yaml(File.read(path))
25
+ metadata = parse_simple_yaml(Hammer.read_text(path))
26
26
  Document.new(
27
27
  file_path: path,
28
28
  metadata: metadata,
@@ -35,7 +35,7 @@ module Hammer
35
35
  end
36
36
 
37
37
  @processed_includes << include_path
38
- included = File.read(File.join(@source_directory, include_path))
38
+ included = Hammer.read_text(File.join(@source_directory, include_path))
39
39
  result.sub!(match[0], "\n#{process_includes(included)}\n")
40
40
  end
41
41
 
data/lib/hammer/ignore.rb CHANGED
@@ -13,7 +13,7 @@ module Hammer
13
13
  path = File.join(source_dir, ".hammer-ignore")
14
14
  return [] unless File.file?(path)
15
15
 
16
- File.read(path, encoding: "UTF-8").each_line.map(&:strip).reject do |line|
16
+ Hammer.read_text(path).each_line.map(&:strip).reject do |line|
17
17
  line.empty? || line.start_with?("#")
18
18
  end
19
19
  end
data/lib/hammer/io.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hammer
4
+ module_function
5
+
6
+ def read_text(path)
7
+ File.binread(path).force_encoding(Encoding::UTF_8)
8
+ end
9
+ end
@@ -54,7 +54,7 @@ module Hammer
54
54
  path = File.join(@build_directory, "sitemap.xml")
55
55
  return [] unless File.file?(path)
56
56
 
57
- File.read(path).scan(%r{<loc>([^<]+)</loc>}).flatten
57
+ Hammer.read_text(path).scan(%r{<loc>([^<]+)</loc>}).flatten
58
58
  end
59
59
 
60
60
  def generate_xml(pages)
@@ -25,7 +25,7 @@ module Hammer
25
25
 
26
26
  def process_file(relative_path, output_path_for_styling: nil)
27
27
  @current_file_path = output_path_for_styling || relative_path
28
- content = File.read(File.join(@source_directory, relative_path))
28
+ content = Hammer.read_text(File.join(@source_directory, relative_path))
29
29
  process_file_content(content, relative_path, output_path_for_styling)
30
30
  end
31
31
 
@@ -167,7 +167,7 @@ module Hammer
167
167
  end
168
168
 
169
169
  @processed_includes << path
170
- included = File.read(File.join(@source_directory, path))
170
+ included = Hammer.read_text(File.join(@source_directory, path))
171
171
  child = self.class.new(
172
172
  source_directory: @source_directory,
173
173
  parent_variables: @parent_variables.merge(@variables),
@@ -374,9 +374,9 @@ module Hammer
374
374
  dirs = %w[assets/img assets/images assets/media images img media]
375
375
  dirs.each do |dir|
376
376
  path = "#{dir}/#{filename}"
377
- found << path if File.exist?(File.join(@source_directory, path))
377
+ found << path if File.file?(File.join(@source_directory, path))
378
378
  end
379
- found << filename if File.exist?(File.join(@source_directory, filename))
379
+ found << filename if File.file?(File.join(@source_directory, filename))
380
380
 
381
381
  if found.empty? || found.length > 1
382
382
  Dir.glob(File.join(@source_directory, "**", "*")).each do |f|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hammer
4
- VERSION = "0.1.0.pre1"
4
+ VERSION = "0.1.0.pre2"
5
5
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "tmpdir"
5
+
6
+ RSpec.describe "UTF-8 file reads under US-ASCII locale" do
7
+ it "reads smart quotes without raising" do
8
+ Dir.mktmpdir do |dir|
9
+ path = File.join(dir, "sample.html")
10
+ File.binwrite(path, "<p>It\u2019s working \u2014 really.</p>".encode("UTF-8"))
11
+
12
+ previous_external = Encoding.default_external
13
+ previous_internal = Encoding.default_internal
14
+ Encoding.default_external = Encoding::US_ASCII
15
+ Encoding.default_internal = Encoding::US_ASCII
16
+
17
+ expect { Hammer.read_text(path) }.not_to raise_error
18
+ expect(Hammer.read_text(path)).to include("really")
19
+
20
+ Encoding.default_external = previous_external
21
+ Encoding.default_internal = previous_internal
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beachio-hammer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre1
4
+ version: 0.1.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Beach.io
@@ -67,6 +67,7 @@ files:
67
67
  - lib/hammer/css_parser.rb
68
68
  - lib/hammer/errors.rb
69
69
  - lib/hammer/ignore.rb
70
+ - lib/hammer/io.rb
70
71
  - lib/hammer/output_formatter.rb
71
72
  - lib/hammer/project_resolver.rb
72
73
  - lib/hammer/sitemap_generator.rb
@@ -76,6 +77,7 @@ files:
76
77
  - scripts/test-classic.rb
77
78
  - scripts/test-content.rb
78
79
  - scripts/tree-diff.rb
80
+ - spec/encoding_spec.rb
79
81
  - spec/parity/classic_spec.rb
80
82
  - spec/parity/content_spec.rb
81
83
  - spec/spec_helper.rb