archival 0.0.4 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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: