{"id":45,"date":"2019-02-01T08:00:00","date_gmt":"2019-02-01T08:00:00","guid":{"rendered":"http:\/\/wcwp.rf.gd\/2019\/02\/01\/https-landscapearchaeology-org-2019-frontmatter\/"},"modified":"2019-02-01T08:00:00","modified_gmt":"2019-02-01T08:00:00","slug":"frontmatter","status":"publish","type":"post","link":"https:\/\/landscapeanalysis.org\/?p=45","title":{"rendered":"Bulk editing posts for Jekyll"},"content":{"rendered":"<p>This website is generated by <a href=\"https:\/\/jekyllrb.com\/\">Jekyll<\/a>, a static site generator. Static sites do not require complex backend engines, such as databases and software which recreate site content for each visitor. It\u2019s just static files. This translates into a) free hosting (it\u2019s cheap to host static files), b) super-fast websites (no software grinding behind) and c) less energy consumption. But it also implies the maintainer doing much of the work that is normally delegated to machines.<\/p>\n<p>Jekyll is for geeks, even if you may read otherwise on the net, no buttons and check boxes here. Managing the content can easily become a pain, especially when we start to deal with larger numbers of articles. These are all just text files sitting on the disk. A typical problem is to remove or to add tags to existing articles. As sites evolve, we introduce new tags and reorganise the old ones.<\/p>\n<p>There is a solution for the management of Jekyll posts in the form of a small Python library called <a href=\"https:\/\/python-frontmatter.readthedocs.io\/en\/latest\/\">frontmatter<\/a>. To install just do:<\/p>\n<div class=\"language-python highlighter-rouge\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code><span class=\"n\">pip<\/span> <span class=\"n\">install<\/span> <span class=\"n\">python<\/span><span class=\"o\">-<\/span><span class=\"n\">frontmatter<\/span>\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>This library can edit data fields in post heading (YAML format) and read post contents. That\u2019s perfect for our problem of bulk editing tag fields, we just need to loop through posts and assign\/remove tags. This is a script I came up with:<\/p>\n<div class=\"language-python highlighter-rouge\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code><span class=\"kn\">import<\/span> <span class=\"nn\">frontmatter<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">os<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">listdir<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">os.path<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">isfile<\/span><span class=\"p\">,<\/span> <span class=\"n\">join<\/span>\n\n<span class=\"kn\">import<\/span> <span class=\"nn\">codecs<\/span> <span class=\"c1\">#this is nasty...\n<\/span>\n<span class=\"s\">\"\"\"\nBulk edit function for tags in Jekyll posts. \n\nThe script will attempt to edit and OVERWRITE ALL FILES \nin the specified folder: \nyou should place selected files in a temporary folder. \n\"\"\"<\/span>\n\n<span class=\"c1\"># -------  INPUT PARAMETERS --------------\n<\/span>\n<span class=\"c1\"># TEMPORARY folder with selected files \n# (do not specify the main _posts folder!)\n<\/span><span class=\"n\">folder<\/span> <span class=\"o\">=<\/span> <span class=\"s\">'__path__to__my__temporary__folder__'<\/span>\n\n<span class=\"n\">add_tag<\/span> <span class=\"o\">=<\/span> <span class=\"s\">'qgis'<\/span> <span class=\"c1\">#tag to be insereted\n<\/span>\n<span class=\"n\">remove_tag<\/span><span class=\"o\">=<\/span> <span class=\"s\">''<\/span> <span class=\"c1\">#tag to be removed\n<\/span>\n<span class=\"c1\"># ----------- ENGINE --------------------\n<\/span>\n<span class=\"k\">for<\/span> <span class=\"n\">f<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">listdir<\/span><span class=\"p\">(<\/span><span class=\"n\">folder<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"nb\">file<\/span> <span class=\"o\">=<\/span> <span class=\"n\">join<\/span> <span class=\"p\">(<\/span><span class=\"n\">folder<\/span><span class=\"p\">,<\/span> <span class=\"n\">f<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">isfile<\/span><span class=\"p\">(<\/span><span class=\"nb\">file<\/span><span class=\"p\">):<\/span> <span class=\"k\">continue<\/span>\n\n    <span class=\"k\">print<\/span> <span class=\"p\">(<\/span><span class=\"nb\">file<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">post<\/span> <span class=\"o\">=<\/span> <span class=\"n\">frontmatter<\/span><span class=\"p\">.<\/span><span class=\"n\">load<\/span> <span class=\"p\">(<\/span><span class=\"nb\">file<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\">#print (post['title'])\n<\/span>\t\n    <span class=\"k\">if<\/span> <span class=\"n\">remove_tag<\/span> <span class=\"p\">:<\/span>\n        <span class=\"k\">try<\/span><span class=\"p\">:<\/span>  <span class=\"n\">post<\/span><span class=\"p\">[<\/span><span class=\"s\">'tags'<\/span><span class=\"p\">].<\/span><span class=\"n\">remove<\/span><span class=\"p\">(<\/span><span class=\"n\">remove_tag<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">except<\/span><span class=\"p\">:<\/span> <span class=\"k\">pass<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">add_tag<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">try<\/span><span class=\"p\">:<\/span>\n            <span class=\"k\">if<\/span> <span class=\"n\">add_tag<\/span> <span class=\"ow\">not<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">post<\/span><span class=\"p\">[<\/span><span class=\"s\">'tags'<\/span><span class=\"p\">]<\/span> <span class=\"p\">:<\/span>\n                <span class=\"n\">post<\/span><span class=\"p\">[<\/span><span class=\"s\">'tags'<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"p\">[<\/span><span class=\"n\">add_tag<\/span><span class=\"p\">]<\/span>\n        <span class=\"k\">except<\/span><span class=\"p\">:<\/span>\n            <span class=\"c1\"># tags do not exist yet\n<\/span>            <span class=\"n\">post<\/span><span class=\"p\">.<\/span><span class=\"n\">metadata<\/span><span class=\"p\">[<\/span><span class=\"s\">'tags'<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"n\">add_tag<\/span><span class=\"p\">]<\/span>\n\n  \n\t<span class=\"c1\"># this is the output in text format\n<\/span>    <span class=\"n\">out<\/span> <span class=\"o\">=<\/span> <span class=\"n\">frontmatter<\/span><span class=\"p\">.<\/span><span class=\"n\">dumps<\/span><span class=\"p\">(<\/span><span class=\"n\">post<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># https:\/\/stackoverflow.com\/questions\/934160\/write-to-utf-8-file-in-python\/934203#934203\n<\/span>    <span class=\"n\">o<\/span> <span class=\"o\">=<\/span> <span class=\"n\">codecs<\/span><span class=\"p\">.<\/span><span class=\"nb\">open<\/span><span class=\"p\">(<\/span><span class=\"nb\">file<\/span><span class=\"p\">,<\/span> <span class=\"s\">'w'<\/span><span class=\"p\">,<\/span> <span class=\"s\">'utf-8'<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">o<\/span><span class=\"p\">.<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"n\">out<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">o<\/span><span class=\"p\">.<\/span><span class=\"n\">close<\/span><span class=\"p\">()<\/span>\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>IMPORTANT: the script will attempt to edit all files in a folder, there is no particular filter or whatever. You should never run it inside the main folder containing original posts. Copy selected posts to a temporary folder, edit, check and then paste back to the main <em>_posts<\/em> folder (or wherever these may be placed).<\/p>\n<p>Note that data fields are represented as keys in a dictionary, which is handy ( <code class=\"language-python highlighter-rouge\"><span class=\"k\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">post<\/span><span class=\"p\">[<\/span><span class=\"s\">'title'<\/span><span class=\"p\">])<\/span><\/code> ). This script can be extended for other data fields (date, author name, title etc\u2026).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This website is generated by Jekyll, a static site generator. Static sites do not require complex backend engines, such as databases and software which recreate site content for each visitor. It\u2019s just static files. This translates into a) free hosting (it\u2019s cheap to host static files), b) super-fast websites (no software grinding behind) and c) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[8],"class_list":["post-45","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-code"],"_links":{"self":[{"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=\/wp\/v2\/posts\/45","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=45"}],"version-history":[{"count":0,"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=\/wp\/v2\/posts\/45\/revisions"}],"wp:attachment":[{"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=45"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=45"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/landscapeanalysis.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=45"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}