ddfreyne on 4.12.1
Always write stack trace backwa… Merge branch 'stack-trace-alway… Expand paths in a more backward… and 5 more (compare)
ddfreyne on 4.12.0
ddfreyne on main
Always write stack trace backwa… Merge branch 'stack-trace-alway… Expand paths in a more backward… and 5 more (compare)
ddfreyne on 4.12.1
ddfreyne on bundler
ddfreyne on main
Bump kramdown from 2.3.0 to 2.3… Merge pull request #254 from na… (compare)
ddfreyne on main
Upgrade Rubocop (compare)
dependabot[bot] on bundler
Bump kramdown from 2.3.0 to 2.3… (compare)
ddfreyne on main
Expand paths in filesystem data… Merge branch 'expand-dirs-in-fi… Add universal license at root (compare)
def find_backlinks
backlinks_to = {}
skipped_notes = ["/posts/overview"]
domain = config[:base_url]
# Start with the domain, or be inside a (/...) Markdown inline link or a [...]: reference style link
link_regex = /(?<=#{domain}\/|\(\/|\: \/)(.*?)(?:="|\)|\s|$)/
def remove_trailing_slash(str)
if str[-1..] == "/"
str[...-1]
else
str
end
end
@items.find_all('/posts/**/*').each do |origin|
next if origin.binary?
next if skipped_notes.include?(origin.identifier.without_exts)
# transform links into a format that looks like `identifier.without_ext`
linked_paths = origin.raw_content
.scan(link_regex)
.map { |m| "/" + remove_trailing_slash(m[0]) }
linked_paths.each do |linked_path|
backlinks_to[linked_path] ||= []
backlinks_to[linked_path] << origin.identifier
end
end
@items.find_all('/posts/**/*').each do |target|
next if target.binary?
next if skipped_notes.include?(target.identifier.without_exts)
target[:backlinks] = backlinks_to.fetch(target.identifier.without_exts, [])
end
end
find_backlinks # before adding the tag index etc.
nanoc-live
auto-compiles my sites without mysteriously affecting my Emacs modeline colors. Never figured out why running guard
would do that.
odd observation: def foo;end in lib/default.rb makes foo() available in a preprocess do block, but adding the same right before the preprocess line won't
This has to do with Ruby’s scoping setup. The Rules file is evalulated in one scope, but the individual rules themselves are evaluated in a different one. (And the files in lib/ live in another scope—the global one.)
I also think it’s confusing, but haven’t found an alternative way that works (and remains backwards compatible)!
Hey everyone. I thought I'd come back and post my solution to the problem I asked help with. This preprocess block will use :mtime and a separate (and auto generated) meta file to keep track of the updates and, hopefully, make item[:updated_at] automatically available only when relevant. Maybe there's a simpler way to achieve this but this is the best I got for now!
Thanks for the help!
preprocess do
def prepare_blog_articles
now = Time.now.round
@items.select { |i| i.identifier.to_s =~ %r{^/blog/[^_]} }.each do |item|
if item[:meta_filename]
item_check_updates(item, now)
else
item_first_publish(item, now)
end
end
end
def item_first_publish(item, now)
item[:created_at] = now
item[:last_updated_at] = now
create_meta_file(item, now)
update_mtime(item, now)
end
def item_check_updates(item, now)
# Abnormal cases; if this happens, it was a mistake and must be fixed manually:
abort "#{item[:meta_filename]} should contain 'created_at' info" unless item.key?(:created_at)
abort "#{item[:meta_filename]} should contain 'last_updated_at' info" unless item.key?(:last_updated_at)
# We only set item[:updated_at] if we want that info to appear in the final
# rendering of the item. If the item has never been updated, both fields in
# the meta file should be equal here. Otherwise we use the :last_updated_at
# as the most recent date.
if item[:last_updated_at] != item[:created_at]
item[:updated_at] = item[:last_updated_at]
end
# But maybe the item has been updated but the meta file hasn't. In that
# case, item[:mtime] will not be equal to item[:last_updated_at]. So we set
# the revelant values for NOW and record them. (This may override
# item[:update_at] if it was set in the previously if block, but that is by
# design: it means the item was updated again after the last update.)
if item[:last_updated_at].to_i != item[:mtime].to_i
item[:updated_at] = now
update_meta_file(item, now)
update_mtime(item, now)
end
end
def create_meta_file(item, now)
meta_filename = Pathname(item.raw_filename).sub_ext(".yaml")
File.open(meta_filename, 'wb') { |f| f.write "created_at: #{now}\nlast_updated_at: #{now}\n" }
end
def update_meta_file(item, now)
meta_content = IO.read(item[:meta_filename])
IO.write(item[:meta_filename], meta_content.sub(/^last_updated_at:.+/, "last_updated_at: #{now}"))
end
def update_mtime(item, now)
File.utime(now, now, item.raw_filename)
end
prepare_blog_articles
end
nanoc live
should work, but it doesn't-- "nanoc: unknown command 'live'"
Long time I didn't compile a nanoc site of mine and I'm hitting
Current item: /api.md (:default representation)
0. _factory/lib/items.rb:47:in `path'
1. /usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html/document.rb:171:in `parse'
2. /usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html/document_fragment.rb:42:in `initialize'
3. /usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html/document_fragment.rb:23:in `new'
4. /usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html/document_fragment.rb:23:in `parse'
5. /usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html.rb:31:in `fragment'
6. _factory/lib/filters/rouge.rb:9:in `run'
Somewhat nokogiri
tries to call a path
function which is bound to my own code in lib/
😐
/usr/local/lib/ruby/gems/3.0.0/gems/nokogiri-1.11.3-x86_64-darwin/lib/nokogiri/html/document.rb:171
url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
So yeah for the readers. My items.rb
files was defined the following way
module NanocFactory
module Items
def path(target, params = {})
...
end
end
include NanocFactory::Items
And I never realized it would add a #path()
instance method on all objects!
include NanocFactory::Items
with use_helper NanocFactory::Items
filter
after the Rouge filter would work, too, searching for all [[....]]
occurrences. But I still want to limit these to non-code/non-pre tags.