2016-04-29 5 views
4

Gibt es einen Weg in Ruby, die YAML Frontmatter am Anfang einer Markdown-Datei zu bearbeiten, wie in Jekyll und Middleman?Edit YAML Frontmatter in Markdown-Datei

Etwas wie:

def update_yaml 
    #magic that changes A: 1 to A: 2 in Frontmatter block 
end 

Dann Datei meines Abschlag, die von

--- 
A: 1 
--- 
# Title 
Words. More words. This is the words part of the file. 

zu

--- 
A: 2 
--- 
# Title 
Words. More words. This is the words part of the file. 

Es scheint wie die einzige Möglichkeit, die gesamte Datei Parsen ändern würde, dann Umschreiben der gesamten Datei mit nur dem gewünschten Teil geändert, aber ich hoffe, dass es etwas besseres gibt.

Antwort

0

Einer der Entwickler von Middleman erreichte tatsächlich Twitter und bot eine Middleman-spezifische, aber dennoch sehr großzügige und hilfreiche Antwort. Es ist in der Praxis ähnlich zu den anderen Antworten (zum Zeitpunkt des Schreibens), aber es nutzt einige Middleman-Funktionalität. Ihre Antwort (bearbeitet, um in diesem Zusammenhang Sinn zu machen) ist unten.


Wenn Sie machen ein Skript oder Verlängerung Sie können middleman-core/util/data benötigen die ::Middleman::Util::Data.parse

bietet Dies wird einen Dateinamen und eine Middleman „Quelldatei“ und eine Liste mit Trennzeichen (die --- vor Angelegenheit verwendet) und gibt 2 Werte zurück: ein Datenobjekt der Front und den String-Inhalt des Rests der Datei.

Sie können dieses Ruby-Objekt dann ändern und die Datei schreiben.

So würde das Lesen wie folgt aussehen:

require "middleman-core/util/data” 

resource = app.sitemap.resources.find_resource_by_destination_path(“whatever.html”) 

frontmatter, content = ::Middleman::Util::Data.parse(resource.file_descriptor, app.config[:frontmatter_delims]) 

und Schreiben:

# change frontmatter 

::File.write(resource.source_file, %Q{ 
--- 
#{frontmatter.to_yaml} 
--- 

#{content} 
}) 

Sorry, das Daten-Parsing-Zeug ist ein wenig seltsam (eine spezielle Datei-Descriptor und Konfigurationswert erforderlich), das Zeug wird normalerweise nicht außerhalb des Kerns verwendet.

1

Ich weiß nicht, von etwas besser, aber es ist ziemlich einfach zu implementieren:

require "yaml" 

YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m 

def update_data(data) 
    data.merge("A" => 2) 
end 

if $stdin.read =~ YAML_FRONT_MATTER_REGEXP 
    data, content = YAML.load($1), Regexp.last_match.post_match 
    data = update_data(data) 
    YAML.dump(data, $stdout) 
    $stdout.puts("---", content) 
end 

Die oben liest aus $stdin und schreibe $stdout (siehe es in Aktion on Ideone), aber in der Praxis würden Sie wahrscheinlich wollen Sie read from a file und schreiben Sie auf eine Tempfile, und bei Erfolg ersetzen Sie die ursprüngliche Datei mit der Tempdatei (mit, sagen wir, FileUtils).

Wenn Sie sich fragen, ich stahlen straight from Jekyll und angepasst frontmatter handling code.

2

Ja kann ich viel besser Sie nur das YAML Dokument aus der Quelle gelesen haben und halten an ihrem Ende zu lesen (---), dann bearbeiten Sie Ihre YAML, schreiben Sie es in eine neue Datei aus (die tatsächlich die Länge des Daten könnte sich ändern, also ist es unwahrscheinlich, dass Sie das an Ort und Stelle neu schreiben können), dann lesen Sie den Rest der Eingabedatei, und schreiben Sie es aus.

Das größte Problem, das ich sehe, ist, dass Ihr Ruby-YAML-Parser alle Kommentare, Tag-Namen und mögliche andere Dinge, die YAML im Round-Trip-Prozess lesbar machen, fallen lässt.

2

Kürzlich habe ich das gleiche Problem konfrontiert, als Alternative können Sie python-frontmatter verwenden. Es ist einfach zu bedienen. Hier ist der Code, den Wert einer yaml Variablen zu ändern:

import frontmatter 
    import io 
    with io.open('File.md', 'r') as f: 
     post = frontmatter.load(f) 
     post['A'] = 2 

     # Save the file. 
     newfile = io.open(fname, 'w', encoding='utf8') 
     frontmatter.dump(post, newfile) 
     newfile.close() 

Weitere Beispiele können Sie besuchen this page