archival 0.0.4 → 0.0.8

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: 71c5bb3b87870dd8146038f624251b7a9ef351a7d69f8da16c214c91ea740cfb
4
- data.tar.gz: 6978ae618a2e5312178e5c0d1eb7174c13f3ef0512d0ef31d83f5012e0bd9712
3
+ metadata.gz: 6d3848687ae065595e19f5b75bb50927318e81df6d6b878541b2ef44138f9d31
4
+ data.tar.gz: 7a48ab3c689dcbb886f2441216750729ec892e40d6dc0a39197fba17eb9c4ab2
5
5
  SHA512:
6
- metadata.gz: df27c765403ac93aa5bd762ca7693b589aa86a0a80e31a93226fce2a0a756f2167417036cd76e4c96fda55071f3af92884628ac56f2c42bac8995a799432c32d
7
- data.tar.gz: 4e785cf1c9bc97a152a737bbc03da981a65b8ea68e0b98fe6fc71196da82fbe928170c983f4dd11a857a9b51c4a1e854f268c42137c184ce15312e4dc9f5cc72
6
+ metadata.gz: '039d5ae09373d249e90fd850e7bd68970ae5ad3c394ed452016e4acaca4df5063d1aab818a09f9a365af9e3277b777257c27d2c4cc365b7d8daafcb33842e8a3'
7
+ data.tar.gz: 6246274ed1209a20819616480c7a1ffde1422b1a68bf5e728a3b637e61ac8675e2bc8fafa8a003cedac455e11ca21e5f22ef9039de96d95f1fc5dcab0f93111b
data/.rubocop.yml CHANGED
@@ -30,7 +30,7 @@ Metrics/BlockLength:
30
30
  Max: 150
31
31
 
32
32
  Metrics/ClassLength:
33
- Max: 150
33
+ Max: 200
34
34
 
35
35
  Metrics/CyclomaticComplexity:
36
36
  Max: 10
data/Gemfile CHANGED
@@ -7,4 +7,4 @@ gemspec
7
7
 
8
8
  gem 'rake', '~> 13.0'
9
9
  gem 'rspec', '~> 3.0'
10
- gem 'rubocop', '~> 1.22', require: false
10
+ gem 'rubocop', '~> 1.23', require: false
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.4'
5
+ s.version = '0.0.8'
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']
@@ -24,5 +24,10 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.add_dependency 'liquid', '~> 5.1.0'
26
26
  s.add_dependency 'listen', '~> 3.7.0'
27
+ s.add_dependency 'redcarpet', '~> 3.5.1'
27
28
  s.add_dependency 'tomlrb', '~> 2.0.1'
29
+
30
+ s.metadata = {
31
+ 'rubygems_mfa_required' => 'true'
32
+ }
28
33
  end
data/bin/redcarpet ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'redcarpet' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("redcarpet", "redcarpet")
@@ -2,12 +2,12 @@
2
2
 
3
3
  require 'liquid'
4
4
  require 'tomlrb'
5
- require 'tags/layout'
6
-
7
- Liquid::Template.error_mode = :strict
8
- Liquid::Template.register_tag('layout', Layout)
5
+ require 'redcarpet'
9
6
 
10
7
  module Archival
8
+ class DuplicateKeyError < StandardError
9
+ end
10
+
11
11
  class Builder
12
12
  attr_reader :page_templates
13
13
 
@@ -16,24 +16,31 @@ module Archival
16
16
  refresh_config
17
17
  end
18
18
 
19
+ def pages_dir
20
+ File.join(@config.root, @config.pages_dir)
21
+ end
22
+
23
+ def objects_dir
24
+ File.join(@config.root, @config.objects_dir)
25
+ end
26
+
19
27
  def refresh_config
20
28
  @file_system = Liquid::LocalFileSystem.new(
21
- @config.root, '%s.liquid'
29
+ pages_dir, '%s.liquid'
22
30
  )
23
- @variables = {}
24
31
  @object_types = {}
25
32
  @page_templates = {}
33
+ @dynamic_types = Set.new
34
+ @dynamic_templates = {}
35
+ @parser = Archival::Parser.new(pages_dir)
26
36
 
27
- Liquid::Template.file_system = @file_system
37
+ Liquid::Template.file_system = Liquid::LocalFileSystem.new(
38
+ pages_dir, '_%s.liquid'
39
+ )
28
40
 
29
- objects_definition_file = File.join(@config.root,
30
- 'objects.toml')
31
- if File.file? objects_definition_file
32
- @object_types = read_toml(objects_definition_file)
33
- end
41
+ @objects_definition_file = File.join(@config.root, 'objects.toml')
34
42
 
35
43
  update_pages
36
- update_objects
37
44
  end
38
45
 
39
46
  def full_rebuild
@@ -41,8 +48,46 @@ module Archival
41
48
  refresh_config
42
49
  end
43
50
 
44
- def update_pages
45
- do_update_pages(File.join(@config.root, @config.pages_dir))
51
+ def update_objects(_updated_objects = nil)
52
+ @object_types = {}
53
+ if File.file? @objects_definition_file
54
+ @object_types = Tomlrb.load_file(@objects_definition_file)
55
+ end
56
+ @dynamic_types = Set.new
57
+ @object_types.each do |_name, definition|
58
+ is_template = definition.key? 'template'
59
+ @dynamic_types << definition['template'] if is_template
60
+ end
61
+ # TODO: remove deleted dynamic pages
62
+ end
63
+
64
+ def update_pages(_updated_pages = nil, _updated_objects = nil)
65
+ update_objects
66
+ # TODO: remove deleted pages
67
+ do_update_pages(pages_dir)
68
+ end
69
+
70
+ def update_assets(changes)
71
+ changes.each do |change|
72
+ asset_path = File.join(@config.build_dir, change.path)
73
+ case change.type
74
+ when :removed
75
+ FileUtils.rm_rf asset_path
76
+ else
77
+ puts change.path
78
+ FileUtils.copy_entry File.join(@config.root, change.path), asset_path
79
+ end
80
+ end
81
+ end
82
+
83
+ def dynamic?(file)
84
+ @dynamic_types.include? File.basename(file, '.liquid')
85
+ end
86
+
87
+ def template_for_page(template_file)
88
+ content = @file_system.read_template_file(template_file)
89
+ content += dev_mode_content if @config.dev_mode
90
+ Liquid::Template.parse(content)
46
91
  end
47
92
 
48
93
  def do_update_pages(dir, prefix = nil)
@@ -58,62 +103,96 @@ module Archival
58
103
  add_prefix(entry))
59
104
  end
60
105
  elsif File.file? File.join(dir, entry)
61
- if entry.end_with?('.liquid') && !(entry.start_with? '_')
62
- page_name = File.basename(entry,
63
- '.liquid')
64
- template_file = File.join(
65
- @config.pages_dir,
66
- add_prefix.call(page_name)
67
- )
68
- content = @file_system.read_template_file(template_file)
69
- content += dev_mode_content if @config.dev_mode
70
- @page_templates[add_prefix.call(page_name)] =
71
- Liquid::Template.parse(content)
106
+ page_name = File.basename(entry, '.liquid')
107
+ template_file = add_prefix.call(page_name)
108
+ if dynamic? entry
109
+ @dynamic_templates[template_file] = template_for_page(template_file)
110
+ elsif entry.end_with?('.liquid') && !(entry.start_with? '_')
111
+ @page_templates[template_file] =
112
+ template_for_page(template_file)
72
113
  end
73
114
  end
74
115
  end
75
116
  end
76
117
 
77
- def update_objects
78
- do_update_objects(File.join(@config.root,
79
- @config.objects_dir))
118
+ def read_objects(type)
119
+ obj_dir = File.join(objects_dir, type)
120
+ return unless File.directory? obj_dir
121
+
122
+ Dir.foreach(obj_dir) do |file|
123
+ if file.end_with? '.toml'
124
+ object = Tomlrb.load_file(File.join(
125
+ obj_dir, file
126
+ ))
127
+ object[:name] =
128
+ File.basename(file, '.toml')
129
+ yield object[:name], object
130
+ end
131
+ end
132
+ end
133
+
134
+ def path_for_template(name, type)
135
+ Pathname.new(File.join(pages_dir, type, "#{name}.html"))
80
136
  end
81
137
 
82
- def do_update_objects(dir)
138
+ def objects_for_template(template_path)
83
139
  objects = {}
84
- @object_types.each do |name, _definition|
85
- objects[name] = []
86
- obj_dir = File.join(dir, name)
87
- if File.directory? obj_dir
88
- Dir.foreach(obj_dir) do |file|
89
- if file.end_with? '.toml'
90
- object = read_toml(File.join(
91
- obj_dir, file
92
- ))
93
- object[:name] =
94
- File.basename(file, '.toml')
95
- objects[name].push object
96
- end
140
+ @object_types.each do |type, definition|
141
+ objects[type] = {}
142
+ is_dynamic = @dynamic_types.include? type
143
+ read_objects type do |name, object|
144
+ objects[type][name] = @parser.parse_object(
145
+ object, definition, template_path
146
+ )
147
+ if is_dynamic
148
+ path = path_for_template(name, type)
149
+ objects[type][name]['path'] =
150
+ path.relative_path_from(File.dirname(template_path)).to_s
97
151
  end
98
152
  end
99
- objects[name] = objects[name].sort do |a, b|
100
- (a['order'] || a[:name]).to_s <=> (b['order'] || b[:name]).to_s
101
- end
153
+ objects[type] = sort_objects(objects[type])
102
154
  end
103
- @variables['objects'] = objects
155
+ objects
104
156
  end
105
157
 
106
- def read_toml(file_path)
107
- Tomlrb.load_file(file_path)
108
- end
158
+ def sort_objects(objects)
159
+ # Sort by either 'order' key or object name, depending on what is
160
+ # available.
161
+ sorted_by_keys = objects.sort_by do |name, obj|
162
+ obj.key?('order') ? obj['order'].to_s : name
163
+ end
164
+ sorted_objects = Archival::TemplateArray.new
165
+ sorted_by_keys.each do |d|
166
+ raise DuplicateKeyError if sorted_objects.key?(d[0])
109
167
 
110
- def set_var(name, value)
111
- @variables[name] = value
168
+ sorted_objects.push(d[1])
169
+ sorted_objects[d[0]] = d[1]
170
+ end
171
+ sorted_objects
112
172
  end
113
173
 
114
174
  def render(page)
175
+ dir = File.join(pages_dir, File.dirname(page))
115
176
  template = @page_templates[page]
116
- template.render(@variables)
177
+ template_path = File.join(dir, page)
178
+ parsed_objects = objects_for_template(template_path)
179
+ template.render('objects' => parsed_objects,
180
+ 'template_path' => template_path)
181
+ end
182
+
183
+ def render_dynamic(type, name)
184
+ dir = File.join(pages_dir, type)
185
+ template = @dynamic_templates[type]
186
+ template_path = File.join(dir, name)
187
+ parsed_objects = objects_for_template(template_path)
188
+ obj = parsed_objects[type][name]
189
+ vars = {}
190
+ .merge(
191
+ 'objects' => parsed_objects,
192
+ 'template_path' => template_path
193
+ )
194
+ .merge({ type => obj })
195
+ template.render(vars)
117
196
  end
118
197
 
119
198
  def write_all
@@ -122,18 +201,29 @@ module Archival
122
201
  out_dir = File.join(@config.build_dir,
123
202
  File.dirname(template))
124
203
  Dir.mkdir(out_dir) unless File.exist? out_dir
125
- out_path = File.join(@config.build_dir,
126
- "#{template}.html")
204
+ out_path = File.join(out_dir, "#{template}.html")
127
205
  File.open(out_path, 'w+') do |file|
128
206
  file.write(render(template))
129
207
  end
130
208
  end
131
- return if @config.dev_mode
209
+ @dynamic_types.each do |type|
210
+ out_dir = File.join(@config.build_dir, type)
211
+ Dir.mkdir(out_dir) unless File.exist? out_dir
212
+ read_objects(type) do |name|
213
+ out_path = File.join(out_dir, "#{name}.html")
214
+ File.open(out_path, 'w+') do |file|
215
+ file.write(render_dynamic(type, name))
216
+ end
217
+ end
218
+ end
132
219
 
133
- # in production, also copy all assets to the dist folder.
220
+ # in production (or init), also copy all assets to the dist folder.
221
+ # in dev, they will be copied as they change.
134
222
  @config.assets_dirs.each do |asset_dir|
135
- FileUtils.copy_entry File.join(@config.root, asset_dir),
136
- File.join(@config.build_dir, asset_dir)
223
+ asset_path = File.join(@config.build_dir, asset_dir)
224
+ next if @config.dev_mode || !File.exist?(asset_path)
225
+
226
+ FileUtils.copy_entry File.join(@config.root, asset_dir), asset_path
137
227
  end
138
228
  end
139
229
 
@@ -129,7 +129,7 @@ module Archival
129
129
  end
130
130
  # warn "Unmasked the data: #{unmasked_data.inspect}"
131
131
 
132
- unmasked_data.to_s.pack('C*').force_encoding('utf-8')
132
+ unmasked_data.pack('C*').force_encoding('utf-8')
133
133
  end
134
134
 
135
135
  def ws_sendmessage(message)
@@ -4,6 +4,8 @@ require 'listen'
4
4
  require 'pathname'
5
5
 
6
6
  module Archival
7
+ Change = Struct.new(:path, :type)
8
+
7
9
  def listen(config = {})
8
10
  @config = Config.new(config.merge(dev_mode: true))
9
11
  builder = Builder.new(@config)
@@ -13,21 +15,27 @@ module Archival
13
15
  ignore = %r{/dist/}
14
16
  listener = Listen.to(@config.root,
15
17
  ignore: ignore) do |modified, added, removed|
16
- updated_pages = []
17
- updated_objects = []
18
- updated_assets = []
19
- (modified + added + removed).each do |file|
20
- case change_type(file)
21
- when :pages
22
- updated_pages << file
23
- when :objects
24
- updated_objects << file
25
- when :assets
26
- updated_assets << file
27
- end
18
+ changes = {
19
+ pages: [],
20
+ objects: [],
21
+ assets: [],
22
+ layout: [],
23
+ config: []
24
+ }
25
+ add_change = lambda { |file, type|
26
+ c_type = change_type(file)
27
+ changes[c_type] << change(file, type) unless c_type == :none
28
+ }
29
+ added.each do |file|
30
+ add_change.call(file, :added)
31
+ end
32
+ modified.each do |file|
33
+ add_change.call(file, :modified)
28
34
  end
29
- @server.refresh_client if rebuild?(builder, updated_objects,
30
- updated_pages, updated_assets)
35
+ removed.each do |file|
36
+ add_change.call(file, :removed)
37
+ end
38
+ @server.refresh_client if rebuild?(builder, changes)
31
39
  end
32
40
  listener.start
33
41
  serve_helpers
@@ -45,6 +53,13 @@ module Archival
45
53
  false
46
54
  end
47
55
 
56
+ def change(file, type)
57
+ c = Change.new
58
+ c.path = Pathname.new(file).relative_path_from(@config.root)
59
+ c.type = type
60
+ c
61
+ end
62
+
48
63
  def change_type(file)
49
64
  # a page was modified, rebuild the pages.
50
65
  return :pages if child?(File.join(@config.root, @config.pages_dir),
@@ -53,26 +68,29 @@ module Archival
53
68
  return :objects if child?(File.join(@config.root, @config.objects_dir),
54
69
  file)
55
70
 
56
- # layout and other assets. For now, this is everything.
71
+ # an asset was changed, which just means to copy or delete it
57
72
  @config.assets_dirs.each do |dir|
58
73
  return :assets if child?(File.join(@config.root, dir), file)
59
74
  end
60
- return :assets if child?(File.join(@config.root, 'layout'), file)
61
- return :assets if ['manifest.toml',
75
+ # other special files
76
+ return :layout if child?(File.join(@config.root, 'layout'), file)
77
+ return :config if ['manifest.toml',
62
78
  'objects.toml'].include? File.basename(file)
63
79
 
64
80
  :none
65
81
  end
66
82
 
67
- def rebuild?(builder, updated_objects, updated_pages, updated_assets)
68
- if updated_pages.empty? && updated_objects.empty? && updated_assets.empty?
69
- return false
70
- end
83
+ def rebuild?(builder, changes)
84
+ return false if changes.values.all?(&:empty?)
71
85
 
72
86
  Logger.benchmark('rebuilt') do
73
- builder.update_objects if updated_objects.length
74
- builder.update_pages if updated_pages.length
75
- builder.full_rebuild if updated_assets.length
87
+ if changes[:pages].length || changes[:objects].length
88
+ builder.update_pages(changes[:pages], changes[:objects])
89
+ end
90
+ builder.update_assets(changes[:assets]) if changes[:assets].length
91
+ if changes[:assets].length || changes[:layouts] || changes[:config]
92
+ builder.full_rebuild
93
+ end
76
94
  builder.write_all
77
95
  end
78
96
  true
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redcarpet'
4
+
5
+ module Archival
6
+ class MarkdownRenderer < Redcarpet::Render::HTML
7
+ def autolink(link, _link_type, _opts)
8
+ # TODO: handle link_type?
9
+ "<a href=\"#{rewrite_link(link)}\">#{rewrite_link(link)}</a>"
10
+ end
11
+
12
+ def link(link, title, content)
13
+ "<a href=\"#{rewrite_link(link)}\" title=\"#{title}\">#{content}</a>"
14
+ end
15
+
16
+ def image(link, title, alt_text)
17
+ "<img src=\"#{rewrite_link(link)}\" \
18
+ title=\"#{title}\" alt=\"#{alt_text}\"/>"
19
+ end
20
+
21
+ private
22
+
23
+ def rewrite_link(link)
24
+ if link.start_with?('http') || link.start_with?('mailto') ||
25
+ link.start_with?('www') || link.start_with?('/')
26
+ link
27
+ end
28
+ template_dir = File.dirname(@options[:template_file])
29
+ resolved_link = Pathname.new(File.join(@options[:pages_root], link))
30
+ resolved_link.relative_path_from(template_dir)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'liquid'
4
+ require 'redcarpet'
5
+
6
+ module Archival
7
+ class Parser
8
+ def initialize(pages_root)
9
+ @pages_root = pages_root
10
+ end
11
+
12
+ def parse_object(object, definition, template_file)
13
+ markdown = Redcarpet::Markdown.new(
14
+ Archival::MarkdownRenderer.new(prettify: true,
15
+ hard_wrap: true),
16
+ no_intra_emphasis: true,
17
+ fenced_code_blocks: true,
18
+ autolink: true,
19
+ strikethrough: true,
20
+ underline: true,
21
+ template_file: template_file,
22
+ pages_root: @pages_root
23
+ )
24
+ definition.each do |name, type|
25
+ case type
26
+ when 'markdown'
27
+ object[name] = markdown.render(object[name]) if object.key? name
28
+ end
29
+ end
30
+ object
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Archival
4
+ class TemplateArray < Array
5
+ alias subscript_access []
6
+ alias subscript_write []=
7
+
8
+ def initialize(*args)
9
+ super(*args)
10
+ @data = {}
11
+ end
12
+
13
+ def [](*args)
14
+ key = args[0]
15
+ return @data[key] if key.is_a? String
16
+ return @data[key] if key.is_a? Symbol
17
+
18
+ subscript_access(*args)
19
+ end
20
+
21
+ def []=(*args)
22
+ key = args[0]
23
+ if key.is_a?(String) || key.is_a?(Symbol)
24
+ @data[key] = args[1]
25
+ return
26
+ end
27
+ subscript_write(*args)
28
+ end
29
+
30
+ def key?(key)
31
+ @data.key?(key)
32
+ end
33
+ end
34
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Archival
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.8'
5
5
  end
data/lib/archival.rb CHANGED
@@ -1,12 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'liquid'
4
+ require 'tags/layout'
5
+ require 'tags/asset'
6
+
3
7
  module Archival
4
8
  # Main Archival module. See https://archival.dev for docs.
5
9
  end
6
10
 
11
+ Liquid::Template.error_mode = :strict
12
+ Liquid::Template.register_tag('layout', Layout)
13
+ Liquid::Template.register_tag('asset', Asset)
14
+
7
15
  require 'archival/version'
16
+ require 'archival/template_array'
8
17
  require 'archival/logger'
9
18
  require 'archival/config'
19
+ require 'archival/markdown_renderer'
10
20
  require 'archival/helper_server'
21
+ require 'archival/parser'
11
22
  require 'archival/builder'
12
23
  require 'archival/listen'
data/lib/tags/asset.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'liquid'
4
+
5
+ class Asset < Liquid::Tag
6
+ # Adds an `asset` tag to liquid. Usage:
7
+ #
8
+ # {% asset "path/to/asset.png" %}
9
+ #
10
+ # This will replace the tag with a relative path to the asset from the
11
+ # current template. Using normal tags will work from the root, but when
12
+ # building dynamic pages or reusing layouts, asset paths are dynamic and
13
+ # will need to be rewritten.
14
+
15
+ prepend Liquid::Tag::Disableable
16
+
17
+ SYNTAX = /(#{Liquid::QuotedFragment}+)/o.freeze
18
+
19
+ def initialize(tag_name, markup, tokens)
20
+ super
21
+ raise AssetError, 'Invalid layout syntax' unless markup =~ SYNTAX
22
+
23
+ @path = parse_expression(Regexp.last_match(1))
24
+ # This is defaulted to the pages dir, because it represents the structure
25
+ # of our website. Asset directories are copied as siblings at runtime.
26
+ @@root_dir ||= File.join(Dir.pwd, 'pages')
27
+ end
28
+
29
+ def self.root_dir=(dir)
30
+ @@root_dir = dir
31
+ end
32
+
33
+ def render_to_output_buffer(context, output)
34
+ unless @@root_dir
35
+ raise AssetError,
36
+ 'root_dir must be set on Archival::Asset'
37
+ end
38
+
39
+ unless context.key? 'template_path'
40
+ raise AssetError,
41
+ 'template_path must be provided to parse when using assets'
42
+ end
43
+ 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
46
+ output
47
+ end
48
+ end
49
+
50
+ class AssetError < Liquid::Error
51
+ end
data/lib/tags/layout.rb CHANGED
@@ -25,7 +25,7 @@ class Layout < Liquid::Tag
25
25
  super
26
26
 
27
27
  @page_content = []
28
- raise 'Invalid layout syntax' unless markup =~ SYNTAX
28
+ raise LayoutError, 'Invalid layout syntax' unless markup =~ SYNTAX
29
29
 
30
30
  layout_name = Regexp.last_match(1)
31
31
  @layout_name_expr = parse_expression(layout_name)
@@ -40,7 +40,9 @@ class Layout < Liquid::Tag
40
40
  base_path = Dir.pwd
41
41
  layout_dir = 'layout'
42
42
  layout_path = File.join(base_path, layout_dir)
43
- raise "Layout dir #{layout_path} not found" unless File.exist? layout_path
43
+ unless File.exist? layout_path
44
+ raise LayoutError, "Layout dir #{layout_path} not found"
45
+ end
44
46
 
45
47
  layout_path
46
48
  end
@@ -55,11 +57,15 @@ class Layout < Liquid::Tag
55
57
  )
56
58
 
57
59
  next unless File.basename(f, '.*') == layout_name
58
- raise "More than one layout named #{layout_name} found." if found_layout
60
+ if found_layout
61
+ raise LayoutError, "More than one layout named #{layout_name} found."
62
+ end
59
63
 
60
64
  found_layout = File.join(layout_path, f)
61
65
  end
62
- raise "No layouts named #{layout_name} found." if found_layout.nil?
66
+ if found_layout.nil?
67
+ raise LayoutError, "No layouts named #{layout_name} found."
68
+ end
63
69
 
64
70
  layout = File.read(found_layout)
65
71
  @@layout_cache[layout_name] =
@@ -77,7 +83,7 @@ class Layout < Liquid::Tag
77
83
 
78
84
  def render_to_output_buffer(context, output)
79
85
  layout_name = context.evaluate(@layout_name_expr)
80
- raise 'Bad layout name argument' unless layout_name
86
+ raise LayoutError, 'Bad layout name argument' unless layout_name
81
87
 
82
88
  layout = load_layout(layout_name)
83
89
 
@@ -104,3 +110,6 @@ class Layout < Liquid::Tag
104
110
  output
105
111
  end
106
112
  end
113
+
114
+ class LayoutError < Liquid::Error
115
+ end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archival",
3
- "version": "0.0.4",
3
+ "version": "0.0.8",
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.4
4
+ version: 0.0.8
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-07 00:00:00.000000000 Z
11
+ date: 2021-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.7.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: redcarpet
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.5.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.5.1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: tomlrb
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -76,6 +90,7 @@ files:
76
90
  - bin/ldiff
77
91
  - bin/listen
78
92
  - bin/rake
93
+ - bin/redcarpet
79
94
  - bin/rspec
80
95
  - bin/rubocop
81
96
  - bin/ruby-parse
@@ -89,14 +104,19 @@ files:
89
104
  - lib/archival/helper_server.rb
90
105
  - lib/archival/listen.rb
91
106
  - lib/archival/logger.rb
107
+ - lib/archival/markdown_renderer.rb
108
+ - lib/archival/parser.rb
92
109
  - lib/archival/rake_tasks.rb
110
+ - lib/archival/template_array.rb
93
111
  - lib/archival/version.rb
112
+ - lib/tags/asset.rb
94
113
  - lib/tags/layout.rb
95
114
  - package.json
96
115
  homepage: https://archival.dev
97
116
  licenses:
98
117
  - Unlicense
99
- metadata: {}
118
+ metadata:
119
+ rubygems_mfa_required: 'true'
100
120
  post_install_message:
101
121
  rdoc_options: []
102
122
  require_paths: