#!/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