Python to Ruby
This commit is contained in:
1 parent
cf82698bef
commit
4c9e1f5f66
13 files changed
+360
-711
No files matched your search
Executable
+144
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "json"
|
||||
require_relative "schema"
|
||||
|
||||
ROOT = File.expand_path("..", __dir__)
|
||||
CONTENT = File.join(ROOT, "src", "content")
|
||||
|
||||
|
||||
def error(path, message)
|
||||
label = path ? "#{path.delete_prefix(ROOT + "/")} : " : ""
|
||||
warn "ERREUR : #{label}#{message}"
|
||||
$errors += 1
|
||||
end
|
||||
|
||||
$errors = 0
|
||||
|
||||
if ARGV.any?
|
||||
warn "Usage : #{File.basename($PROGRAM_NAME)}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
def front_matter(path)
|
||||
text = File.read(path, encoding: "UTF-8")
|
||||
match = text.match(/\A\+\+\+\r?\n(.*?)\r?\n\+\+\+(?:\r?\n|\z)/m)
|
||||
unless match
|
||||
error(path, "front matter délimité par +++ absent")
|
||||
return nil
|
||||
end
|
||||
match[1]
|
||||
rescue StandardError => e
|
||||
error(path, "lecture impossible (#{e.message})")
|
||||
nil
|
||||
end
|
||||
|
||||
def fields_by_table(source)
|
||||
tables = Hash.new { |hash, key| hash[key] = {} }
|
||||
table = "root"
|
||||
|
||||
source.each_line do |line|
|
||||
line = line.strip
|
||||
next if line.empty? || line.start_with?("#")
|
||||
|
||||
if (match = line.match(/\A\[([^\]]+)\]\z/))
|
||||
table = match[1]
|
||||
elsif (match = line.match(/\A([A-Za-z_][A-Za-z0-9_-]*)\s*=\s*(.*)\z/))
|
||||
tables[table][match[1]] = match[2]
|
||||
end
|
||||
end
|
||||
|
||||
tables
|
||||
end
|
||||
|
||||
def check_filename(path, section)
|
||||
stem = File.basename(path, ".md")
|
||||
error(path, "nom de fichier non normalisé en Unicode NFC") if stem != stem.unicode_normalize(:nfc)
|
||||
|
||||
if section == "signes"
|
||||
match = stem.match(/\Amzl-([0-9]{3})\z/)
|
||||
error(path, "un signe doit être nommé mzl-NNN.md (001 à 999)") unless match && match[1].to_i.between?(1, 999)
|
||||
return
|
||||
end
|
||||
|
||||
leading_hyphen = stem.start_with?("-")
|
||||
body = leading_hyphen ? stem[1..] : stem
|
||||
if leading_hyphen && section != "vocabulaire"
|
||||
error(path, "seul le vocabulaire accepte un nom commençant par un tiret")
|
||||
return
|
||||
end
|
||||
|
||||
valid = body && !body.empty? &&
|
||||
stem != "_index" &&
|
||||
stem == stem.downcase &&
|
||||
!stem.end_with?("-") &&
|
||||
!stem.include?("--") &&
|
||||
body.match?(/\A[\p{Alnum}-]+\z/u)
|
||||
|
||||
error(path, "nom de fichier invalide : utiliser des lettres Unicode minuscules, des chiffres et des tirets") unless valid
|
||||
end
|
||||
|
||||
def require_fields(path, tables, table, fields)
|
||||
missing = fields.reject { |field| tables.fetch(table, {}).key?(field) }
|
||||
error(path, "champs #{table} manquants : #{missing.join(', ')}") unless missing.empty?
|
||||
end
|
||||
|
||||
unless Dir.exist?(CONTENT)
|
||||
error(nil, "répertoire introuvable : #{CONTENT}")
|
||||
else
|
||||
puts "Vérification des fiches…"
|
||||
Dir.glob(File.join(CONTENT, "**", "*.md")).sort.each do |path|
|
||||
relative = path.delete_prefix(CONTENT + "/")
|
||||
parts = relative.split("/")
|
||||
next if File.basename(path) == "_index.md" || parts.length == 1
|
||||
|
||||
section = parts.first
|
||||
unless CONTENT_SECTIONS.include?(section)
|
||||
error(path, "section inconnue : #{section}")
|
||||
next
|
||||
end
|
||||
|
||||
check_filename(path, section)
|
||||
source = front_matter(path)
|
||||
next unless source
|
||||
|
||||
tables = fields_by_table(source)
|
||||
require_fields(path, tables, "root", %w[title date description draft])
|
||||
error(path, "la fiche doit contenir exactement une ligne updated") unless source.scan(UPDATED_RE).length == 1
|
||||
|
||||
if section == "vocabulaire"
|
||||
value = tables.dig("taxonomies", "natures")
|
||||
unless value
|
||||
error(path, "champ taxonomies manquant : natures")
|
||||
next
|
||||
end
|
||||
|
||||
begin
|
||||
natures = JSON.parse(value)
|
||||
rescue JSON::ParserError
|
||||
natures = nil
|
||||
end
|
||||
|
||||
unless natures.is_a?(Array) && natures.length == 1 && natures.first.is_a?(String)
|
||||
error(path, "taxonomies.natures doit contenir exactement une nature")
|
||||
next
|
||||
end
|
||||
|
||||
nature = natures.first
|
||||
fields = VOCABULARY_FIELDS[nature]
|
||||
if fields
|
||||
require_fields(path, tables, "extra", fields)
|
||||
else
|
||||
error(path, "nature grammaticale inconnue : #{nature.inspect}")
|
||||
end
|
||||
else
|
||||
SECTION_FIELDS.fetch(section).each do |table, fields|
|
||||
require_fields(path, tables, table, fields)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
puts "\nRésultat : #{$errors} erreur(s)."
|
||||
exit($errors.zero? ? 0 : 1)
|
||||
Reference in new issue
Block a user