Files
lescarnetsdakkadien.netig.net/scripts/new-content.rb
T
2026-09-30 14:27:05 +02:00

99 lines
3.5 KiB
Ruby
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env ruby
# frozen_string_literal: true
require "json"
require "optparse"
require "time"
require_relative "schema"
ENV["TZ"] = "Europe/Paris"
ROOT = File.expand_path("..", __dir__)
CONTENT = File.join(ROOT, "src", "content")
options = {}
parser = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} SECTION IDENTIFIANT [options]"
opts.on("--nature NATURE", "nature d’une fiche de vocabulaire") { |value| options[:nature] = value }
opts.on("--title TITRE", "titre initial") { |value| options[:title] = value }
end
begin
parser.parse!
raise "SECTION et IDENTIFIANT sont requis, sans argument supplémentaire" unless ARGV.length == 2
section_name, identifier = ARGV
section = SECTION_ALIASES[section_name]
raise "section inconnue : #{section_name}" unless section
normalize = ->(value) { value.strip.unicode_normalize(:nfc) }
identifier = normalize.call(identifier)
if section == "signes"
match = identifier.match(/\A(?:mzl-)?([0-9]{1,3})\z/)
raise "le numéro MZL doit être compris entre 1 et 999" unless match && match[1].to_i.between?(1, 999)
mzl = format("%03d", match[1].to_i)
filename = "mzl-#{mzl}"
else
leading_hyphen = identifier.start_with?("-")
body = leading_hyphen ? identifier[1..] : identifier
raise "seul le vocabulaire accepte un identifiant commençant par un tiret" if leading_hyphen && section != "vocabulaire"
valid = body && !body.empty? && identifier != "_index" && identifier == identifier.downcase &&
!identifier.end_with?("-") && !identifier.include?("--") && body.match?(/\A[\p{Alnum}-]+\z/u)
raise "identifiant de fichier invalide" unless valid
filename = identifier
end
nature = options[:nature]&.unicode_normalize(:nfc)
if section == "vocabulaire"
raise "--nature est requis pour le vocabulaire" unless nature
raise "nature grammaticale inconnue : #{nature}" unless VOCABULARY_FIELDS.key?(nature)
elsif nature
raise "--nature est réservé au vocabulaire"
end
title = if options[:title]
normalize.call(options[:title])
elsif section == "signes"
""
elsif section == "vocabulaire"
filename
else
filename.tr("-", " ").sub(/\A./) { |char| char.upcase }
end
tables = if section == "vocabulaire"
{
"extra" => VOCABULARY_FIELDS.fetch(nature).to_h { |field| [field, LIST_FIELDS.include?(field) ? [] : ""] },
"taxonomies" => { "natures" => [nature] }
}
else
SECTION_FIELDS.fetch(section).transform_values do |fields|
fields.to_h { |field| [field, LIST_FIELDS.include?(field) ? [] : ""] }
end
end
tables["extra"]["mzl"] = mzl if section == "signes"
lines = [
"+++",
"title = #{JSON.generate(title)}",
"date = #{Time.now.iso8601}",
"# updated = YYYY-MM-DDTHH:MM:SS+HH:MM",
'description = ""',
"draft = true"
]
tables.each do |table, fields|
lines << ""
lines << "[#{table}]"
fields.each { |field, value| lines << "#{field} = #{JSON.generate(value)}" }
end
lines += ["+++", ""]
destination = File.join(CONTENT, section, "#{filename}.md")
File.open(destination, File::WRONLY | File::CREAT | File::EXCL, 0o644) { |file| file.write(lines.join("\n")) }
puts "Brouillon créé : #{destination.delete_prefix(ROOT + '/')}"
rescue OptionParser::ParseError, RuntimeError, Errno::EEXIST, SystemCallError => e
warn "Erreur : #{e.message}"
exit 1
end