archival 0.0.8 → 0.0.11

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: 6d3848687ae065595e19f5b75bb50927318e81df6d6b878541b2ef44138f9d31
4
- data.tar.gz: 7a48ab3c689dcbb886f2441216750729ec892e40d6dc0a39197fba17eb9c4ab2
3
+ metadata.gz: c44af9438c108896c1e5c3f6577708a150525305045a5e0bd183700b49f20234
4
+ data.tar.gz: 4033a7f2b80d88eab1d4071552398716f1592b6c07ec34acc00d36613d30f49b
5
5
  SHA512:
6
- metadata.gz: '039d5ae09373d249e90fd850e7bd68970ae5ad3c394ed452016e4acaca4df5063d1aab818a09f9a365af9e3277b777257c27d2c4cc365b7d8daafcb33842e8a3'
7
- data.tar.gz: 6246274ed1209a20819616480c7a1ffde1422b1a68bf5e728a3b637e61ac8675e2bc8fafa8a003cedac455e11ca21e5f22ef9039de96d95f1fc5dcab0f93111b
6
+ metadata.gz: ddad0158c303b58e247f6e974dc22ef0967936c113afa7f090a9302cd4cd890512f58b2136b0aabecec6ddfc8ae29c242a0f8ee7a2842734241c783942820792
7
+ data.tar.gz: ef1663df39febc76cf51af9eedfcf106db95712bf8f96d51e76e94e8daa4bd0a5d9133e0e2971e696a74add29bb4f3214da3a13d400b0711e64861678c753571
data/.rubocop.yml CHANGED
@@ -30,7 +30,7 @@ Metrics/BlockLength:
30
30
  Max: 150
31
31
 
32
32
  Metrics/ClassLength:
33
- Max: 200
33
+ Max: 250
34
34
 
35
35
  Metrics/CyclomaticComplexity:
36
36
  Max: 10
data/README.md CHANGED
@@ -53,6 +53,18 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
53
53
 
54
54
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
55
55
 
56
+ To point a local archival site at a local version, run inside the website dir:
57
+
58
+ ```
59
+ bundle config local.archival /path/to/local/git/repository
60
+ ```
61
+
62
+ Then comment out the archival dependency in Gemfile and add:
63
+
64
+ ```
65
+ gem 'archival', github: 'jesseditson/archival', branch: 'main'
66
+ ```
67
+
56
68
  ## Contributing
57
69
 
58
70
  Bug reports and pull requests are welcome on GitHub at https://github.com/jesseditson/archival.
data/archival.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'archival'
5
- s.version = '0.0.8'
5
+ s.version = '0.0.11'
6
6
  s.summary = 'An incredibly simple CMS for durable websites'
7
7
  s.description = 'https://jesseditson.com/the-simplest-cms-part-1'
8
8
  s.authors = ['Jesse Ditson']
data/bin/bundle CHANGED
@@ -73,7 +73,7 @@ m = Module.new do
73
73
 
74
74
  requirement = bundler_gem_version.approximate_recommendation
75
75
 
76
- return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
76
+ return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
77
77
 
78
78
  requirement += ".a" if bundler_gem_version.prerelease?
79
79
 
@@ -3,17 +3,23 @@
3
3
  require 'liquid'
4
4
  require 'tomlrb'
5
5
  require 'redcarpet'
6
+ require 'fileutils'
7
+ require 'tags/asset'
6
8
 
7
9
  module Archival
8
10
  class DuplicateKeyError < StandardError
9
11
  end
10
12
 
13
+ class DuplicateStaticFileError < StandardError
14
+ end
15
+
11
16
  class Builder
12
17
  attr_reader :page_templates
13
18
 
14
19
  def initialize(config, *_args)
15
20
  @config = config
16
21
  refresh_config
22
+ Asset.helper_port = @config.helper_port
17
23
  end
18
24
 
19
25
  def pages_dir
@@ -221,14 +227,40 @@ module Archival
221
227
  # in dev, they will be copied as they change.
222
228
  @config.assets_dirs.each do |asset_dir|
223
229
  asset_path = File.join(@config.build_dir, asset_dir)
224
- next if @config.dev_mode || !File.exist?(asset_path)
230
+ next if @config.dev_mode && File.exist?(asset_path)
231
+
232
+ source_path = File.join(@config.root, asset_dir)
233
+ next unless File.exist?(source_path)
225
234
 
226
- FileUtils.copy_entry File.join(@config.root, asset_dir), asset_path
235
+ FileUtils.copy_entry source_path, asset_path
227
236
  end
237
+
238
+ copy_static
228
239
  end
229
240
 
230
241
  private
231
242
 
243
+ def copy_static
244
+ static_dir = File.join(@config.root, @config.static_dir)
245
+
246
+ # same for the static dir, but just the content.
247
+ return unless File.exist?(static_dir)
248
+
249
+ copied_static_files = Set[Dir.children(@config.build_dir)]
250
+ Dir.children(static_dir).each do |child|
251
+ raise DuplicateStaticFileError if copied_static_files.include?(child)
252
+
253
+ copied_static_files << child
254
+ asset_path = File.join(@config.build_dir, child)
255
+ next if @config.dev_mode && File.exist?(asset_path)
256
+
257
+ source_path = File.join(static_dir, child)
258
+ next unless File.exist?(source_path)
259
+
260
+ FileUtils.copy_entry source_path, asset_path
261
+ end
262
+ end
263
+
232
264
  def dev_mode_content
233
265
  "<script src=\"http://localhost:#{@config.helper_port}/js/archival-helper.js\" type=\"application/javascript\"></script>" # rubocop:disable Layout/LineLength
234
266
  end
@@ -4,8 +4,8 @@ require 'tomlrb'
4
4
 
5
5
  module Archival
6
6
  class Config
7
- attr_reader :pages_dir, :objects_dir, :assets_dirs, :root, :build_dir,
8
- :helper_port, :dev_mode
7
+ attr_reader :pages_dir, :objects_dir, :static_dir, :assets_dirs, :root,
8
+ :build_dir, :helper_port, :dev_mode
9
9
 
10
10
  def initialize(config = {})
11
11
  @root = config['root'] || Dir.pwd
@@ -17,6 +17,7 @@ module Archival
17
17
  )
18
18
  @helper_port = config['helper_port'] || manifest['helper_port'] || 2701
19
19
  @assets_dirs = config['assets_dirs'] || manifest['assets'] || []
20
+ @static_dir = config['static_dir'] || manifest['static'] || 'static'
20
21
  @dev_mode = config[:dev_mode] || false
21
22
  end
22
23
 
@@ -44,16 +44,23 @@ module Archival
44
44
  MAGIC_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
45
45
 
46
46
  def handle_request(client, req, method, path)
47
- if method == 'GET' && path.start_with?('/js/')
48
- # For static paths, just serve the files they refer to.
47
+ if method == 'GET' && path.start_with?('/js/archival-helper.js')
48
+ # For this special file, serve it from the helper dir
49
49
  http_response(client, type: 'application/javascript') do
50
- serve_static(client, path)
50
+ serve_static(client, path, @helper_dir)
51
51
  end
52
52
  client.close
53
53
  elsif (matches = req.match(/^Sec-WebSocket-Key: (\S+)/))
54
54
  websocket_key = matches[1]
55
55
  # puts "Websocket handshake detected with key: #{websocket_key}"
56
56
  connect_socket(client, websocket_key)
57
+ elsif method == 'GET'
58
+ # For static paths, just serve the files they refer to.
59
+ # TODO: mime type should be inferred from file type
60
+ http_response(client, type: 'application/javascript') do
61
+ serve_static(client, path)
62
+ end
63
+ client.close
57
64
  else
58
65
  client.close
59
66
  end
@@ -99,8 +106,9 @@ module Archival
99
106
 
100
107
  # Our server only supports single-frame, text messages.
101
108
  # Raise an exception if the client tries to send anything else.
102
- raise "We don't support continuations" unless fin
103
- raise 'We only support opcode 1' unless opcode == 1
109
+ raise 'Archival dev server does not support continuations' unless fin
110
+ # Some browsers send this regardless, so ignore it to keep the noise down.
111
+ return unless opcode == 1
104
112
 
105
113
  second_byte = @socket.getbyte
106
114
  is_masked = second_byte & 0b10000000
@@ -119,15 +127,17 @@ module Archival
119
127
  # warn "Payload size: #{payload_size} bytes"
120
128
 
121
129
  mask = 4.times.map { @socket.getbyte }
122
- # warn "Got mask: #{mask.inspect}"
130
+ # warn "Got mask: #{mask.inspect}"
123
131
 
124
132
  data = payload_size.times.map { @socket.getbyte }
125
- # warn "Got masked data: #{data.inspect}"
133
+ # warn "Got masked data: #{data.inspect}"
134
+
135
+ return unless data[0]
126
136
 
127
137
  unmasked_data = data.each_with_index.map do |byte, i|
128
138
  byte ^ mask[i % 4]
129
139
  end
130
- # warn "Unmasked the data: #{unmasked_data.inspect}"
140
+ # warn "Unmasked the data: #{unmasked_data.inspect}"
131
141
 
132
142
  unmasked_data.pack('C*').force_encoding('utf-8')
133
143
  end
@@ -139,8 +149,8 @@ module Archival
139
149
  @socket.write output.pack("CCA#{message.size}")
140
150
  end
141
151
 
142
- def serve_static(client, path)
143
- buffer = File.open(File.join(@helper_dir, path)).read
152
+ def serve_static(client, path, base = @build_dir)
153
+ buffer = File.open(File.join(base, path)).read
144
154
  buffer.sub! '$PORT', @port.to_s
145
155
  client.print buffer
146
156
  end
@@ -150,6 +160,7 @@ module Archival
150
160
  type = config[:type] ||= 'text/html'
151
161
  client.print "HTTP/1.1 #{status}\r\n"
152
162
  client.print "Content-Type: #{type}\r\n"
163
+ client.print "Access-Control-Allow-Origin: *\r\n"
153
164
  client.print "\r\n"
154
165
  yield
155
166
  end
@@ -72,6 +72,11 @@ module Archival
72
72
  @config.assets_dirs.each do |dir|
73
73
  return :assets if child?(File.join(@config.root, dir), file)
74
74
  end
75
+
76
+ # a static file was changed - copy or delete those too.
77
+ return :assets if child?(File.join(@config.root, @config.static_dir),
78
+ file)
79
+
75
80
  # other special files
76
81
  return :layout if child?(File.join(@config.root, 'layout'), file)
77
82
  return :config if ['manifest.toml',
@@ -89,6 +94,8 @@ module Archival
89
94
  end
90
95
  builder.update_assets(changes[:assets]) if changes[:assets].length
91
96
  if changes[:assets].length || changes[:layouts] || changes[:config]
97
+ # TODO: optimization: this could operate on the known subset of
98
+ # changes instead...
92
99
  builder.full_rebuild
93
100
  end
94
101
  builder.write_all
@@ -4,7 +4,7 @@ require 'redcarpet'
4
4
 
5
5
  module Archival
6
6
  class MarkdownRenderer < Redcarpet::Render::HTML
7
- def autolink(link, _link_type, _opts)
7
+ def autolink(link, _opts)
8
8
  # TODO: handle link_type?
9
9
  "<a href=\"#{rewrite_link(link)}\">#{rewrite_link(link)}</a>"
10
10
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Archival
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.11'
5
5
  end
data/lib/tags/asset.rb CHANGED
@@ -14,7 +14,7 @@ class Asset < Liquid::Tag
14
14
 
15
15
  prepend Liquid::Tag::Disableable
16
16
 
17
- SYNTAX = /(#{Liquid::QuotedFragment}+)/o.freeze
17
+ SYNTAX = /(#{Liquid::QuotedFragment}+|\w+)/o.freeze
18
18
 
19
19
  def initialize(tag_name, markup, tokens)
20
20
  super
@@ -24,13 +24,25 @@ class Asset < Liquid::Tag
24
24
  # This is defaulted to the pages dir, because it represents the structure
25
25
  # of our website. Asset directories are copied as siblings at runtime.
26
26
  @@root_dir ||= File.join(Dir.pwd, 'pages')
27
+
28
+ @attributes = {}
29
+
30
+ markup.scan(Liquid::TagAttributes) do |key, value|
31
+ @attributes[key] = parse_expression(value)
32
+ end
27
33
  end
28
34
 
29
35
  def self.root_dir=(dir)
30
36
  @@root_dir = dir
31
37
  end
32
38
 
39
+ def self.helper_port=(port)
40
+ @@helper_port = port
41
+ end
42
+
33
43
  def render_to_output_buffer(context, output)
44
+ path = @path
45
+ path = path.evaluate(context) if path.is_a? Liquid::VariableLookup
34
46
  unless @@root_dir
35
47
  raise AssetError,
36
48
  'root_dir must be set on Archival::Asset'
@@ -41,8 +53,13 @@ class Asset < Liquid::Tag
41
53
  'template_path must be provided to parse when using assets'
42
54
  end
43
55
  template_path = File.dirname(context['template_path'])
44
- abs_asset_path = Pathname.new(File.join(@@root_dir, @path))
45
- output << abs_asset_path.relative_path_from(template_path).to_s
56
+ abs_asset_path = Pathname.new(File.join(@@root_dir, path))
57
+ asset_path = abs_asset_path.relative_path_from(template_path).cleanpath.to_s
58
+ output << if @attributes['serve'] == true
59
+ "http://localhost:#{@@helper_port}/#{asset_path}"
60
+ else
61
+ asset_path
62
+ end
46
63
  output
47
64
  end
48
65
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archival",
3
- "version": "0.0.8",
3
+ "version": "0.0.11",
4
4
  "description": "An incredibly simple CMS for durable websites",
5
5
  "bin": "build.rb",
6
6
  "directories": {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: archival
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Ditson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-22 00:00:00.000000000 Z
11
+ date: 2022-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -132,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubygems_version: 3.2.22
135
+ rubygems_version: 3.3.3
136
136
  signing_key:
137
137
  specification_version: 4
138
138
  summary: An incredibly simple CMS for durable websites