[
  {
    "path": ".eleventy.js",
    "content": "const { DateTime } = require(\"luxon\");\nconst CleanCSS = require(\"clean-css\");\nconst UglifyJS = require(\"uglify-es\");\nconst htmlmin = require(\"html-minifier\");\nconst svgContents = require(\"eleventy-plugin-svg-contents\");\nconst mdIterator = require('markdown-it-for-inline')\nconst embedEverything = require(\"eleventy-plugin-embed-everything\");\nconst pluginTOC = require('eleventy-plugin-nesting-toc');\nconst eleventyNavigationPlugin = require(\"@11ty/eleventy-navigation\");\nconst Image = require(\"@11ty/eleventy-img\");\nconst fs = require('fs');\nmodule.exports = function(eleventyConfig) {\n  // eleventyConfig.addPlugin(pluginTOC);\n  eleventyConfig.addPlugin(svgContents); \n  eleventyConfig.addPlugin(embedEverything);\n  eleventyConfig.addShortcode(\"version\", function () {\n    return String(Date.now());\n  });\n\n  // Responsive image shortcode\n  eleventyConfig.addLiquidShortcode(\"image\", async function(src, alt, sizes = \"100vw\") {\n    if(alt === undefined) {\n      // You bet we throw an error on missing alt (alt=\"\" works okay)\n      throw new Error(`Missing \\`alt\\` on responsiveimage from: ${src}`);\n    }\n    src = './content/images/'+src\n    let metadata = await Image(src, {\n      widths: [400, 600, 800, 1000, 1200, 1400, 1600, 1900],\n      formats: ['webp', 'jpeg', 'png'],\n      urlPath: \"/content/images/\",\n      outputDir: \"./_site/content/images/\"\n    });\n\n    let lowsrc = metadata.jpeg[0];\n\n    let picture = `<picture>\n      ${Object.values(metadata).map(imageFormat => {\n        return `  <source type=\"image/${imageFormat[0].format}\" srcset=\"${imageFormat.map(entry => entry.srcset).join(\", \")}\" sizes=\"${sizes}\">`;\n      }).join(\"\\n\")}\n        <img\n          data-src=\"${lowsrc.url}\"\n          width=\"${lowsrc.width}\"\n          height=\"${lowsrc.height}\"\n          alt=\"${alt}\">\n      </picture>`;\n\n      return `${picture}`;\n\n  });\n\n  eleventyConfig.addLiquidShortcode(\"icon\", function(title,url) {\n    return '<img class=\"icon\" src=\"'+url+'\" alt=\"'+title+'\" />';\n  });\n\n  // Button shortcode -- experimental\n  // eleventyConfig.addLiquidShortcode(\"button\", function(title,url) {\n  //   return '<a class=\"button\" href=\"'+url+'\">'+title+'</a>';\n  // });\n\n\n  // Tailwind pass through and watch target\n  eleventyConfig.addWatchTarget(\"./_tmp/style.css\");\n  eleventyConfig.addPassthroughCopy({ \"./_tmp/style.css\": \"./style.css\" });\n\n  // Alpine.js pass through\n  eleventyConfig.addPassthroughCopy({\n    \"./node_modules/alpinejs/dist/alpine.js\": \"./js/alpine.js\",\n  });\n\n  // Eleventy Navigation https://www.11ty.dev/docs/plugins/navigation/\n  eleventyConfig.addPlugin(eleventyNavigationPlugin);\n\n  // Configuration API: use eleventyConfig.addLayoutAlias(from, to) to add\n  // layout aliases! Say you have a bunch of existing content using\n  // layout: post. If you don’t want to rewrite all of those values, just map\n  // post to a new file like this:\n  // eleventyConfig.addLayoutAlias(\"post\", \"layouts/my_new_post_layout.njk\");\n\n  // Merge data instead of overriding\n  // https://www.11ty.dev/docs/data-deep-merge/\n  eleventyConfig.setDataDeepMerge(true);\n\n  // Add support for maintenance-free post authors\n  // Adds an authors collection using the author key in our post frontmatter\n  // Thanks to @pdehaan: https://github.com/pdehaan\n  // eleventyConfig.addCollection(\"authors\", collection => {\n  //   const blogs = collection.getFilteredByGlob(\"posts/*.md\");\n  //   return blogs.reduce((coll, post) => {\n  //     const author = post.data.author;\n  //     if (!author) {\n  //       return coll;\n  //     }\n  //     if (!coll.hasOwnProperty(author)) {\n  //       coll[author] = [];\n  //     }\n  //     coll[author].push(post.data);\n  //     return coll;\n  //   }, {});\n  // });\n\n   // Creates custom collection \"pages\"\n   eleventyConfig.addCollection(\"pages\", function(collection) {\n    return collection.getFilteredByGlob(\"pages/*.md\");\n   });\n\n   // Creates custom collection \"posts\"\n  //  eleventyConfig.addCollection(\"posts\", function(collection) {\n  //   const coll = collection.getFilteredByGlob(\"posts/*.md\");\n  \n  //   for(let i = 0; i < coll.length ; i++) {\n  //     const prevPost = coll[i-1];\n  //     const nextPost = coll[i + 1];\n  \n  //     coll[i].data[\"prevPost\"] = prevPost;\n  //     coll[i].data[\"nextPost\"] = nextPost;\n  //   }\n  \n  //   return coll;\n  // });\n    \n\n   // Creates custom collection \"results\" for search\n   const searchFilter = require(\"./filters/searchFilter\");\n   eleventyConfig.addFilter(\"search\", searchFilter);\n   eleventyConfig.addCollection(\"results\", collection => {\n    return [...collection.getFilteredByGlob(\"**/*.md\")];\n   });\n  \n   // Creates custom collection \"menuItems\"\n  eleventyConfig.addCollection(\"menuItems\", collection => {\n    const coll = collection\n    .getFilteredByGlob(\"manuscript/*.md\")\n    .sort((a, b) => {\n        return (a.data.eleventyNavigation.order || 0) - (b.data.eleventyNavigation.order || 0);\n      })\n    return coll;\n  });\n\n  // Date formatting (human readable)\n  eleventyConfig.addFilter(\"readableDate\", dateObj => {\n    return DateTime.fromJSDate(dateObj).toFormat(\"LLL dd, yyyy\");\n  });\n\n  // Date formatting (machine readable)\n  eleventyConfig.addFilter(\"machineDate\", dateObj => {\n\n    return DateTime.fromJSDate(dateObj).toFormat(\"yyyy-MM-dd\");\n  });\n\n  // Minify CSS\n  eleventyConfig.addFilter(\"cssmin\", function(code) {\n    return new CleanCSS({}).minify(code).styles;\n  });\n\n  // Minify JS\n  eleventyConfig.addFilter(\"jsmin\", function(code) {\n    let minified = UglifyJS.minify(code);\n    if (minified.error) {\n      console.log(\"UglifyJS error: \", minified.error);\n      return code;\n    }\n    return minified.code;\n  });\n\n  // Minify HTML output\n  eleventyConfig.addTransform(\"htmlmin\", function(content, outputPath) {\n    if (outputPath.indexOf?.(\".html\") > -1) {\n      let minified = htmlmin.minify(content, {\n        useShortDoctype: true,\n        removeComments: true,\n        collapseWhitespace: true\n      });\n      return minified;\n    }\n    return content;\n  });\n\n  // Don't process folders with static assets e.g. images\n  eleventyConfig.addPassthroughCopy(\"favicon.ico\");\n  eleventyConfig.addPassthroughCopy(\"images/\")\n  eleventyConfig.addPassthroughCopy(\"content/images/\")\n  eleventyConfig.addPassthroughCopy(\"admin\");\n  eleventyConfig.addPassthroughCopy(\"_includes/assets/\");\n  eleventyConfig.addPassthroughCopy(\"_includes/experimental/\");\n\n  /* Markdown Plugins */\n  let markdownIt = require(\"markdown-it\");\n  let markdownItAnchor = require(\"markdown-it-anchor\");\n  let markdownItEmoji = require(\"markdown-it-emoji\");\n  let markdownItFootnote = require(\"markdown-it-footnote\");\n  let markdownItContainer = require(\"markdown-it-container\");\n  let markdownLinkifyImages = require('markdown-it-linkify-images')\n  let markdownToc = require('markdown-it-table-of-contents')\n  let markdownItTasks = require('markdown-it-task-lists')\n  let markdownItAttrs = require(\"markdown-it-attrs\")\n  let markdownItCenterText = require(\"markdown-it-center-text\")\n  let options = {\n    html: true,\n    breaks: false,\n    linkify: true,\n    typographer: true\n  };\n  let opts = {\n    // permalink: true,\n    // permalinkClass: \"direct-link\",\n    // permalinkSymbol: \"#\"\n  };\n\n  eleventyConfig.setLibrary(\"md\", markdownIt(options)\n    .use(mdIterator, 'url_new_win', 'link_open', function (tokens, idx) {\n      const [attrName, href] = tokens[idx].attrs.find(attr => attr[0] === 'href')\n      if (href && (!href.includes('franknoirot.co') && !href.startsWith('/') && !href.startsWith('#'))) {\n        tokens[idx].attrPush([ 'target', '_blank' ])\n        tokens[idx].attrPush([ 'rel', 'noopener noreferrer' ])\n      }\n    })\n    .use(markdownItAnchor, opts)\n    .use(markdownItEmoji)\n    .use(markdownItFootnote)\n    .use(markdownItContainer, 'callout')\n    .use(markdownItContainer, 'callout-blue')\n    .use(markdownItContainer, 'callout-pink')\n    .use(markdownItContainer, 'callout-green')\n    .use(markdownItContainer, 'warning')\n    .use(markdownItTasks)\n    .use(markdownItCenterText)\n    .use(markdownLinkifyImages, {\n      imgClass: \"p-4\",\n    })\n    .use(markdownItAttrs, {\n      includeLevel: [2,3],\n      listType: \"ol\"\n    })\n  );\n\n  return {\n    templateFormats: [\"md\", \"njk\", \"html\", \"liquid\"],\n\n    // If your site lives in a different subdirectory, change this.\n    // Leading or trailing slashes are all normalized away, so don’t worry about it.\n    // If you don’t have a subdirectory, use \"\" or \"/\" (they do the same thing)\n    // This is only used for URLs (it does not affect your file structure)\n    pathPrefix: \"/\",\n    markdownTemplateEngine: \"liquid\",\n    htmlTemplateEngine: \"njk\",\n    dataTemplateEngine: \"njk\",\n    dir: {\n      input: \".\",\n      includes: \"_includes\",\n      data: \"_data\",\n      output: \"_site\"\n    }\n  };\n};"
  },
  {
    "path": ".eleventyignore",
    "content": "README.md\n.github/\nfunctions/*\nfunctions/\n"
  },
  {
    "path": ".forestry/settings.yml",
    "content": "---\nnew_page_extension: md\nauto_deploy: false\nadmin_path: ''\nwebhook_url: \nsections:\n- type: directory\n  path: ''\n  label: Test\n  create: all\n  match: \"**/*\"\nupload_dir: uploads\npublic_path: \"/uploads\"\nfront_matter_path: ''\nuse_front_matter_path: true\nfile_template: \":filename:\"\nbuild:\n  preview_env:\n  - ELEVENTY_ENV=dev\n  preview_output_directory: _site\n  install_dependencies_command: npm install\n  preview_docker_image: forestryio/node:12\n  mount_path: \"/srv\"\n  working_dir: \"/srv\"\n  instant_preview_command: npx @11ty/eleventy --serve\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n\n# Standard to msysgit\n*.doc\t diff=astextplain\n*.DOC\t diff=astextplain\n*.docx diff=astextplain\n*.DOCX diff=astextplain\n*.dot  diff=astextplain\n*.DOT  diff=astextplain\n*.pdf  diff=astextplain\n*.PDF\t diff=astextplain\n*.rtf\t diff=astextplain\n*.RTF\t diff=astextplain\n\n\n_site/\nnode_modules/\npackage-lock.json\n.idea\n.vscode\n*~\n"
  },
  {
    "path": ".gitignore",
    "content": "_site/\nnode_modules/\npackage-lock.json\n.idea\n.vscode\n*~\n.cache\n_tmp"
  },
  {
    "path": ".nvmrc",
    "content": "v14\n"
  },
  {
    "path": "404.md",
    "content": "---\ntitle: 404\npermalink: /404.html\nlayout: layouts/404.njk\n---\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Tim Broeker \n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Creative Commons\nAttribution-NonCommercial-NoDerivs 3.0 Unported\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. \n\nLicense\n\nTHE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE (\"CCPL\" OR \"LICENSE\"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.\n\nBY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.\n\n1. Definitions\n\n    \"Adaptation\" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image (\"synching\") will be considered an Adaptation for the purpose of this License.\n    \"Collection\" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.\n    \"Distribute\" means to make available to the public the original and copies of the Work through sale or other transfer of ownership.\n    \"Licensor\" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.\n    \"Original Author\" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.\n    \"Work\" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.\n    \"You\" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.\n    \"Publicly Perform\" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.\n    \"Reproduce\" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.\n\n2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.\n\n3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:\n\n    to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and,\n    to Distribute and Publicly Perform the Work including as incorporated in Collections.\n\nThe above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d).\n\n4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:\n\n    You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested.\n    You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.\n    If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution (\"Attribution Parties\") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.\n\n    For the avoidance of doubt:\n        Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;\n        Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,\n        Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b).\n    Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation.\n\n5. Representations, Warranties and Disclaimer\n\nUNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.\n\n6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n7. Termination\n\n    This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.\n    Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.\n\n8. Miscellaneous\n\n    Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.\n    If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.\n    No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.\n    This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.\n    The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.\n\n    Creative Commons Notice\n\n    Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.\n\n    Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark \"Creative Commons\" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of this License.\n\n    Creative Commons may be contacted at https://creativecommons.org/."
  },
  {
    "path": "README.md",
    "content": "# Prose for Programmers\n\nThis is a book for programmers.\nIt is a guide to mastering the most difficult programming language of all: human language.\n\nJust as with programming,\nwe write with particular goals in mind.\nThat goal might be as simple as reminding someone about a requirement\nor as complex as justifying an entirely new architecture for a product.\nBut in every case we write in order to achieve something.\n\nThis book will teach you how to achieve those goals more effectively with clearer, more persuasive writing.\n\n## It is a work in progress\n\nThe first three chapters are content complete.\n\n* [Why should developers study writing?](manuscript/why.md)\n* [General Rules](manuscript/rules.md)\n* [The Writing Process](manuscript/process.md)\n\nAnd there are four chapters to come.\n\n* Writing Structures\n* Audience\n* Genres\n* Other Resources\n\nFor more detail, take a look at [the outline](outline.md).\n\n## Can I get it in EPUB/MOBI/PDF?\n\n[Yes, you can.](https://leanpub.com/proseforprogrammers)\n\n## Contributing\n\n* For general questions and suggestions, please [open an issue][issues].\n* To correct typos or suggest specific changes in the way something is written, please [open a pull request][prs].\n\nNote: By contributing content to this repository, you grant the book author (Joshua Clanton) a non-exclusive license to use that content in the book as he deems appropriate.\n\n## License\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-nd/3.0/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png\" /></a><br /><span xmlns:dct=\"http://purl.org/dc/terms/\" href=\"http://purl.org/dc/dcmitype/Text\" property=\"dct:title\" rel=\"dct:type\">Prose for Programmers</span> by <span xmlns:cc=\"http://creativecommons.org/ns#\" property=\"cc:attributionName\">Joshua Clanton</span> is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-nd/3.0/\">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License</a>.\n\n[issues]:https://github.com/joshuacc/prose-for-programmers/issues\n[prs]:https://github.com/joshuacc/prose-for-programmers/pulls"
  },
  {
    "path": "_data/site.json",
    "content": "{\n  \"name\": \"Prose for Programmers\",\n  \"subtitle\": \"Learn to write for people, not just computers\",\n  \"description\": \"Learn to write for people, not just computers\",\n  \"footer\": \"<span xmlns:dct='http://purl.org/dc/terms/' href='http://purl.org/dc/dcmitype/Text' property='dct:title' rel='dct:type'><i>Prose for Programmers</i></span> by <span xmlns:cc='http://creativecommons.org/ns#' property='cc:attributionName'>Joshua Clanton</span> is licensed under a <a rel='license' href='http://creativecommons.org/licenses/by-nc-nd/3.0/'>Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License</a>.\",\n  \"url\": \"https://spacebook.app\",\n  \"githubUrl\": \"https://github.com/joshuacc/prose-for-programmers\",\n  \"githubBranch\": \"master\",\n  \"navigationStyle\": \"vertical\",\n  \"emoji\": \"✍🏻\",\n  \"enableSearch\": false,\n  \"enableDarkMode\": true,\n  \"enableEditButton\": true,\n  \"enableDatestamp\": true,\n  \"enableGithubLink\": true,\n  \"enableContact\": false,\n  \"enableNetlifyCMS\": false,\n  \"enableComments\": false,\n  \"enableEncryption\": false,\n  \"enablePageNavigation\": true\n}\n"
  },
  {
    "path": "_includes/assets/css/404.css",
    "content": "html,\nbody {\n    height: 100%;\n    width: 100%;\n    margin: 0px;\n    background: linear-gradient(90deg, #2f3640 23%, #181b20 100%);\n}\n\n.moon {\n    background: linear-gradient(90deg, #d0d0d0 48%, #919191 100%);\n    position: absolute;\n    top: -100px;\n    left: -300px;\n    width: 900px;\n    height: 900px;\n    content: '';\n    border-radius: 100%;\n    box-shadow: 0px 0px 30px -4px rgba(0, 0, 0, 0.5);\n}\n\n.moon__crater {\n    position: absolute;\n    content: '';\n    border-radius: 100%;\n    background: linear-gradient(90deg, #7a7a7a 38%, #c3c3c3 100%);\n    opacity: 0.6;\n}\n\n.moon__crater1 {\n    top: 250px;\n    left: 500px;\n    width: 60px;\n    height: 180px;\n}\n\n.moon__crater2 {\n    top: 650px;\n    left: 340px;\n    width: 40px;\n    height: 80px;\n    transform: rotate(55deg);\n}\n\n.moon__crater3 {\n    top: -20px;\n    left: 40px;\n    width: 65px;\n    height: 120px;\n    transform: rotate(250deg);\n}\n\n.star {\n    background: grey;\n    position: absolute;\n    width: 5px;\n    height: 5px;\n    content: '';\n    border-radius: 100%;\n    transform: rotate(250deg);\n    opacity: 0.4;\n    animation-name: shimmer;\n    animation-duration: 1.5s;\n    animation-iteration-count: infinite;\n    animation-direction: alternate;\n}\n\n@keyframes shimmer {\n    from {\n        opacity: 0;\n    }\n    to {\n        opacity: 0.7;\n    }\n}\n\n.star1 {\n    top: 40%;\n    left: 50%;\n    animation-delay: 1s;\n}\n\n.star2 {\n    top: 60%;\n    left: 90%;\n    animation-delay: 3s;\n}\n\n.star3 {\n    top: 10%;\n    left: 70%;\n    animation-delay: 2s;\n}\n\n.star4 {\n    top: 90%;\n    left: 40%;\n}\n\n.star5 {\n    top: 20%;\n    left: 30%;\n    animation-delay: 0.5s;\n}\n\n.error {\n    position: absolute;\n    left: 100px;\n    top: 400px;\n    transform: translateY(-60%);\n    font-family: 'Righteous', cursive, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n    color: #363e49;\n}\n\n.error__title {\n    font-size: 10em;\n}\n\n.error__subtitle {\n    font-size: 2em;\n}\n\n.error__description {\n    opacity: 0.5;\n}\n\n.error__button {\n    min-width: 7em;\n    margin-top: 3em;\n    margin-right: 0.5em;\n    padding: 0.5em 2em;\n    outline: none;\n    border: 2px solid #2f3640;\n    background-color: transparent;\n    border-radius: 8em;\n    color: #576375;\n    cursor: pointer;\n    transition-duration: 0.2s;\n    font-size: 0.75em;\n    font-family: 'Righteous', cursive,ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";;\n}\n\n.error__button:hover {\n    color: #21252c;\n}\n\n.error__button--active {\n    background-color: #e67e22;\n    border: 2px solid #e67e22;\n    color: white;\n}\n\n.error__button--active:hover {\n    box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.5);\n    color: white;\n}\n\n.astronaut {\n    position: absolute;\n    width: 185px;\n    height: 300px;\n    left: 70%;\n    top: 50%;\n    transform: translate(-50%, -50%) rotate(20deg) scale(1.2);\n}\n\n.astronaut__head {\n    background-color: white;\n    position: absolute;\n    top: 60px;\n    left: 60px;\n    width: 60px;\n    height: 60px;\n    content: '';\n    border-radius: 2em;\n}\n\n.astronaut__head-visor-flare1 {\n    background-color: #7f8fa6;\n    position: absolute;\n    top: 28px;\n    left: 40px;\n    width: 10px;\n    height: 10px;\n    content: '';\n    border-radius: 2em;\n    opacity: 0.5;\n}\n\n.astronaut__head-visor-flare2 {\n    background-color: #718093;\n    position: absolute;\n    top: 40px;\n    left: 38px;\n    width: 5px;\n    height: 5px;\n    content: '';\n    border-radius: 2em;\n    opacity: 0.3;\n}\n\n.astronaut__backpack {\n    background-color: #bfbfbf;\n    position: absolute;\n    top: 90px;\n    left: 47px;\n    width: 86px;\n    height: 90px;\n    content: '';\n    border-radius: 8px;\n}\n\n.astronaut__body {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 115px;\n    left: 55px;\n    width: 70px;\n    height: 80px;\n    content: '';\n    border-radius: 8px;\n}\n\n.astronaut__body__chest {\n    background-color: #d9d9d9;\n    position: absolute;\n    top: 140px;\n    left: 68px;\n    width: 45px;\n    height: 25px;\n    content: '';\n    border-radius: 6px;\n}\n\n.astronaut__arm-left1 {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 127px;\n    left: 9px;\n    width: 65px;\n    height: 20px;\n    content: '';\n    border-radius: 8px;\n    transform: rotate(-30deg);\n}\n\n.astronaut__arm-left2 {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 102px;\n    left: 7px;\n    width: 20px;\n    height: 45px;\n    content: '';\n    border-radius: 8px;\n    transform: rotate(-12deg);\n    border-top-left-radius: 8em;\n    border-top-right-radius: 8em;\n}\n\n.astronaut__arm-right1 {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 113px;\n    left: 100px;\n    width: 65px;\n    height: 20px;\n    content: '';\n    border-radius: 8px;\n    transform: rotate(-10deg);\n}\n\n.astronaut__arm-right2 {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 78px;\n    left: 141px;\n    width: 20px;\n    height: 45px;\n    content: '';\n    border-radius: 8px;\n    transform: rotate(-10deg);\n    border-top-left-radius: 8em;\n    border-top-right-radius: 8em;\n}\n\n.astronaut__arm-thumb-left {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 110px;\n    left: 21px;\n    width: 10px;\n    height: 6px;\n    content: '';\n    border-radius: 8em;\n    transform: rotate(-35deg);\n}\n\n.astronaut__arm-thumb-right {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 90px;\n    left: 133px;\n    width: 10px;\n    height: 6px;\n    content: '';\n    border-radius: 8em;\n    transform: rotate(20deg);\n}\n\n.astronaut__wrist-left {\n    background-color: #e67e22;\n    position: absolute;\n    top: 122px;\n    left: 6.5px;\n    width: 21px;\n    height: 4px;\n    content: '';\n    border-radius: 8em;\n    transform: rotate(-15deg);\n}\n\n.astronaut__wrist-right {\n    background-color: #e67e22;\n    position: absolute;\n    top: 98px;\n    left: 141px;\n    width: 21px;\n    height: 4px;\n    content: '';\n    border-radius: 8em;\n    transform: rotate(-10deg);\n}\n\n.astronaut__leg-left {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 188px;\n    left: 50px;\n    width: 23px;\n    height: 75px;\n    content: '';\n    transform: rotate(10deg);\n}\n\n.astronaut__leg-right {\n    background-color: #e6e6e6;\n    position: absolute;\n    top: 188px;\n    left: 108px;\n    width: 23px;\n    height: 75px;\n    content: '';\n    transform: rotate(-10deg);\n}\n\n.astronaut__foot-left {\n    background-color: white;\n    position: absolute;\n    top: 240px;\n    left: 43px;\n    width: 28px;\n    height: 20px;\n    content: '';\n    transform: rotate(10deg);\n    border-radius: 3px;\n    border-top-left-radius: 8em;\n    border-top-right-radius: 8em;\n    border-bottom: 4px solid #e67e22;\n}\n\n.astronaut__foot-right {\n    background-color: white;\n    position: absolute;\n    top: 240px;\n    left: 111px;\n    width: 28px;\n    height: 20px;\n    content: '';\n    transform: rotate(-10deg);\n    border-radius: 3px;\n    border-top-left-radius: 8em;\n    border-top-right-radius: 8em;\n    border-bottom: 4px solid #e67e22;\n}"
  },
  {
    "path": "_includes/assets/css/inline.css",
    "content": ""
  },
  {
    "path": "_includes/assets/js/404.js",
    "content": "(function (window, document) {\n    \"use strict\";\n    window.addEventListener('load', function () {\n        const cordCanvas = document.getElementById('cord');\n        const ctx = cordCanvas.getContext('2d');\n        \n        let y1 = 160;\n        let y2 = 100;\n        let y3 = 100;\n        \n        let y1Forward = true;\n        let y2Forward = false;\n        let y3Forward = true;\n        drawVisor()\n        //animate()\n    });\n  })(window, document);\n\nfunction drawVisor() {\n    const canvas = document.getElementById('visor');\n    const ctx = canvas.getContext('2d');\n    \n    ctx.beginPath();\n    ctx.moveTo(5, 45);\n    ctx.bezierCurveTo(15, 64, 45, 64, 55, 45);\n    \n    ctx.lineTo(55, 20);\n    ctx.bezierCurveTo(55, 15, 50, 10, 45, 10);\n    \n    ctx.lineTo(15, 10);\n    \n    ctx.bezierCurveTo(15, 10, 5, 10, 5, 20);\n    ctx.lineTo(5, 45);\n    \n    ctx.fillStyle = '#2f3640';\n    ctx.strokeStyle = '#f5f6fa';\n    ctx.fill();\n    ctx.stroke();\n  }\n  \n\n  \n  function animate() {\n    requestAnimationFrame(animate);\n    ctx.clearRect(0, 0, innerWidth, innerHeight);\n    \n    ctx.beginPath();\n    ctx.moveTo(130, 170);\n    ctx.bezierCurveTo(250, y1, 345, y2, 400, y3);\n    \n    ctx.strokeStyle = 'white';\n    ctx.lineWidth = 8;\n    ctx.stroke();\n   \n    \n    if (y1 === 100) {\n      y1Forward = true;\n    }\n    \n    if (y1 === 300) {\n      y1Forward = false;\n    }\n    \n    if (y2 === 100) {\n      y2Forward = true;\n    }\n    \n    if (y2 === 310) {\n      y2Forward = false;\n    }\n    \n    if (y3 === 100) {\n      y3Forward = true;\n    }\n    \n    if (y3 === 317) {\n      y3Forward = false;\n    }\n    \n    y1Forward ? y1 += 1 : y1 -= 1;\n    y2Forward ? y2 += 1 : y2 -= 1;\n    y3Forward ? y3 += 1 : y3 -= 1;\n  }\n  "
  },
  {
    "path": "_includes/assets/js/inline.js",
    "content": "if (window.netlifyIdentity) {\n  window.netlifyIdentity.on(\"init\", user => {\n    if (!user) {\n      window.netlifyIdentity.on(\"login\", () => {\n        document.location.href = \"/admin/\";\n      });\n    }\n  });\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n  \n  const el = document.getElementById(\"main\");\n  el.addEventListener(\"click\", closeNavigation, false)\n\n  if (localStorage.getItem('darkmode') === 'true') {\n    document.body.classList.add(\"dark\");\n  } else {\n    document.body.classList.remove(\"dark\");\n  }\n});\n\nfunction logout() {\n  localStorage.removeItem(\"passphrase\")\n  window.location.href = \"/\";\n}\n\nfunction showNavigation() {\n  const navigation = document.getElementById(\"navigation\");\n  navigation.classList.remove(\"hidden\", \"sticky\",\"pt-32\"); \n  navigation.classList.add(\"absolute\",\"right-0\", \"top-0\", \"-mt-0\", \"z-50\", \"pt-0\", \"bg-white\",\"border-l\", \"border-gray-200\"); \n}\n\nfunction closeNavigation() {\n  const navigation = document.getElementById(\"navigation\");\n  navigation.classList.add(\"hidden\"); \n  navigation.classList.remove(\"absolute\",\"right-0\",\"z-50\", \"bg-gray-100\", \"border-r\", \"border-gray-800\" ); \n}\n\nfunction activateDarkMode() {\n  if (localStorage.getItem('darkmode') === 'true') {\n    localStorage.setItem('darkmode', 'false')\n    document.body.classList.remove(\"dark\");\n  } else {\n    localStorage.setItem('darkmode', 'true')\n    document.body.classList.add(\"dark\");\n  }\n}\n\nfunction toggleLayout(state) {\n  if (localStorage.getItem('layout') === \"horizontal\") {\n    localStorage.setItem('layout', 'vertical')\n  } else if (localStorage.getItem('layout') === \"vertical\") {\n    localStorage.setItem('layout', \"horizontal\")\n  } else if (!localStorage.getItem('layout')) {\n    if (state === \"horizontal\") {\n      localStorage.setItem('layout', 'vertical')\n    } else {\n      localStorage.setItem('layout', 'horizontal')\n    }\n  } \n  \n \n  console.log(localStorage.getItem('layout'))\n}"
  },
  {
    "path": "_includes/assets/js/search.js",
    "content": "(function (window, document) {\n    \"use strict\";\n    const search = (e) => {\n      const results = window.searchIndex.search(e.target.value, {\n        bool: \"OR\",\n        expand: true,\n      });\n      const searchBox = document.getElementById(\"searchField\");\n      const resEl = document.getElementById(\"searchResults\");\n      const noResultsEl = document.getElementById(\"noResultsFound\");\n      const navigation = document.getElementById(\"navigation\");\n\n      searchBox.addEventListener('focus', (event) => {\n        event.target.classList.remove(\"hidden\"); \n        resEl.classList.remove(\"hidden\"); \n      });\n\n    document.addEventListener('click', function(event) {\n        var isClickInside = searchBox.contains(event.target);\n        if (!isClickInside) {\n            console.log('hidden')\n            resEl.classList.add(\"hidden\"),noResultsEl.classList.add(\"hidden\")\n            noResultsEl.classList.add(\"hidden\")\n        }\n      });\n\n    resEl.innerHTML = \"\";\n      if (e.target.value != \"\") {\n        if (results != \"\") {\n          noResultsEl.classList.add(\"hidden\")\n          resEl.classList.add(\"p-4\")\n          results.map((r) => {\n            const { id, title, description } = r.doc;\n            const el = document.createElement(\"li\", { tabindex: '-1' });\n            resEl.appendChild(el);\n    \n            const h3 = document.createElement(\"h3\");\n            el.appendChild(h3);\n    \n            const a = document.createElement(\"a\");\n            a.setAttribute(\"href\", id);\n            a.textContent = title;\n            h3.appendChild(a);\n    \n            const p = document.createElement(\"p\");\n            p.textContent = description;\n            el.appendChild(p);\n          });\n        } else {\n          noResultsEl.classList.remove(\"hidden\")\n        }\n      } else {\n        noResultsEl.classList.add(\"hidden\")\n      }\n    };\n    fetch(\"/search-index.json\").then((response) =>\n      response.json().then((rawIndex) => {\n        window.searchIndex = elasticlunr.Index.load(rawIndex);\n        document.getElementById(\"searchField\").addEventListener(\"input\", search);\n      })\n    );\n  })(window, document);"
  },
  {
    "path": "_includes/assets/utils/image.txt",
    "content": "{% image \"sagan.jpg\" \"Carl Sagan, 1987\" %}"
  },
  {
    "path": "_includes/assets/utils/imagesize.txt",
    "content": "{% image \"sagan.jpg\" \"Carl Sagan, 1987\" \"200px\" %}"
  },
  {
    "path": "_includes/components/contact.njk",
    "content": "<div class=\"flex w-full\">\n  <div class=\"w-full bg-white dark:bg-gray-700 rounded shadow-lg p-8 md:max-w-lg md:mx-auto\">\n    <form name=\"contact\" class=\"mb-4 md:flex md:flex-wrap md:justify-between\" action=\"/\" method=\"post\"  netlify>\n    <h1>Send a message</h1>\n      <div class=\"flex flex-col mb-4 md:w-1/2\">\n        <label class=\"mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest dark:text-gray-400\" for=\"first_name\">First Name</label>\n        <input class=\"border py-2 px-3 text-grey-darkest md:mr-2\" type=\"text\" name=\"first_name\" id=\"first_name\">\n      </div>\n      <div class=\"flex flex-col mb-4 md:w-1/2\">\n        <label class=\"mb-2 uppercase font-bold text-lg text-grey-darkest dark:text-gray-400 md:ml-2\" for=\"last_name\">Last Name</label>\n        <input class=\"border py-2 px-3 text-grey-darkest md:ml-2\" type=\"text\" name=\"last_name\" id=\"last_name\">\n      </div>\n      <div class=\"flex flex-col mb-4 md:w-full\">\n        <label class=\"mb-2 uppercase font-bold text-lg text-grey-darkest dark:text-gray-400\" for=\"email\">Email</label>\n        <input class=\"border py-2 px-3 text-grey-darkest\" type=\"email\" name=\"email\" id=\"email\">\n      </div>\n      <div class=\"flex flex-col mb-6 md:w-full\">\n        <label class=\"mb-2 uppercase font-bold text-lg text-grey-darkest dark:text-gray-400\" for=\"message\">Message</label>\n        <textarea class=\"border py-2 px-3 text-grey-darkest\" name=\"message\" id=\"message\" placeholder=\"Write your message here\" rows=\"7\" required></textarea>\n      </div>\n      <button class=\"block bg-green-600 hover:bg-blue-600 text-white uppercase text-lg mx-auto p-4 rounded\" type=\"submit\">Send message</button>\n    </form>\n  </div>\n</div>\n"
  },
  {
    "path": "_includes/components/footer.njk",
    "content": "<div class=\"z-50 mt-12 h-12 flex dark:bg-gray-900 text-gray-500 dark:text-gray-400 justify-center p-2 border-t border-gray-100 dark:border-gray-800\">\n <div class=\"flex w-full items-center \">\n \n  <div class=\"w-6 h-6 flex-none\">\n  {% if site.enableContact == 1 %}\n  <a aria-label=\"Contact\" href=\"/contact\" rel=\"noopener noreferrer\"> \n  <svg width=\"24\" height=\"24\"  class=\"text-gray-500 dark:text-gray-400\" viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M1 3.5l.5-.5h13l.5.5v9l-.5.5h-13l-.5-.5v-9zm1 1.035V12h12V4.536L8.31 8.9H7.7L2 4.535zM13.03 4H2.97L8 7.869 13.03 4z\"/></svg>\n  </a>\n  {% endif %}\n  </div>\n   \n  <div class=\"text-gray-500 flex flex-grow justify-center text-align-center\">\n     <small>\n    {% if site.footer %}\n    {{ site.footer | safe }}\n    {% endif %}\n    </small>\n  </div>\n  {% if site.enableNetlifyCMS == 1 %}\n  <div class=\"flex-none float-right\">\n    <a aria-label=\"Netlify CMS\" href=\"{{metadata.url}}/admin/\" rel=\"noopener noreferrer\" target=\"_blank\"> \n    <svg width=\"24px\" viewBox=\"0 0 16 16\" class=\"bi bi-gear\" class=\"text-gray-300 dark:text-gray-500\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n      <path class=\"text-gray-300 dark:text-gray-500\" fill-rule=\"evenodd\" d=\"M8.837 1.626c-.246-.835-1.428-.835-1.674 0l-.094.319A1.873 1.873 0 0 1 4.377 3.06l-.292-.16c-.764-.415-1.6.42-1.184 1.185l.159.292a1.873 1.873 0 0 1-1.115 2.692l-.319.094c-.835.246-.835 1.428 0 1.674l.319.094a1.873 1.873 0 0 1 1.115 2.693l-.16.291c-.415.764.42 1.6 1.185 1.184l.292-.159a1.873 1.873 0 0 1 2.692 1.116l.094.318c.246.835 1.428.835 1.674 0l.094-.319a1.873 1.873 0 0 1 2.693-1.115l.291.16c.764.415 1.6-.42 1.184-1.185l-.159-.291a1.873 1.873 0 0 1 1.116-2.693l.318-.094c.835-.246.835-1.428 0-1.674l-.319-.094a1.873 1.873 0 0 1-1.115-2.692l.16-.292c.415-.764-.42-1.6-1.185-1.184l-.291.159A1.873 1.873 0 0 1 8.93 1.945l-.094-.319zm-2.633-.283c.527-1.79 3.065-1.79 3.592 0l.094.319a.873.873 0 0 0 1.255.52l.292-.16c1.64-.892 3.434.901 2.54 2.541l-.159.292a.873.873 0 0 0 .52 1.255l.319.094c1.79.527 1.79 3.065 0 3.592l-.319.094a.873.873 0 0 0-.52 1.255l.16.292c.893 1.64-.902 3.434-2.541 2.54l-.292-.159a.873.873 0 0 0-1.255.52l-.094.319c-.527 1.79-3.065 1.79-3.592 0l-.094-.319a.873.873 0 0 0-1.255-.52l-.292.16c-1.64.893-3.433-.902-2.54-2.541l.159-.292a.873.873 0 0 0-.52-1.255l-.319-.094c-1.79-.527-1.79-3.065 0-3.592l.319-.094a.873.873 0 0 0 .52-1.255l-.16-.292c-.892-1.64.902-3.433 2.541-2.54l.292.159a.873.873 0 0 0 1.255-.52l.094-.319z\"/>\n      <path class=\"text-gray-300 dark:text-gray-500\" fill-rule=\"evenodd\" d=\"M8 5.754a2.246 2.246 0 1 0 0 4.492 2.246 2.246 0 0 0 0-4.492zM4.754 8a3.246 3.246 0 1 1 6.492 0 3.246 3.246 0 0 1-6.492 0z\"/>\n    </svg> \n    </a>\n  </div>\n  {% endif %}\n  {% if site.enableGithubLink == 1 %}\n  <div class=\"flex-none ml-2 float-right\">\n    <a aria-label=\"github link\" rel=\"noopener noreferrer\" href=\"{{ site.githubUrl}}\" target=\"_blank\"><svg height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" class=\"text-gray-400 dark:text-gray-400\" d=\"M12 3C7.0275 3 3 7.12937 3 12.2276C3 16.3109 5.57625 19.7597 9.15374 20.9824C9.60374 21.0631 9.77249 20.7863 9.77249 20.5441C9.77249 20.3249 9.76125 19.5982 9.76125 18.8254C7.5 19.2522 6.915 18.2602 6.735 17.7412C6.63375 17.4759 6.19499 16.6569 5.8125 16.4378C5.4975 16.2647 5.0475 15.838 5.80124 15.8264C6.51 15.8149 7.01625 16.4954 7.18499 16.7723C7.99499 18.1679 9.28875 17.7758 9.80625 17.5335C9.885 16.9337 10.1212 16.53 10.38 16.2993C8.3775 16.0687 6.285 15.2728 6.285 11.7432C6.285 10.7397 6.63375 9.9092 7.20749 9.26326C7.1175 9.03257 6.8025 8.08674 7.2975 6.81794C7.2975 6.81794 8.05125 6.57571 9.77249 7.76377C10.4925 7.55615 11.2575 7.45234 12.0225 7.45234C12.7875 7.45234 13.5525 7.55615 14.2725 7.76377C15.9937 6.56418 16.7475 6.81794 16.7475 6.81794C17.2424 8.08674 16.9275 9.03257 16.8375 9.26326C17.4113 9.9092 17.76 10.7281 17.76 11.7432C17.76 15.2843 15.6563 16.0687 13.6537 16.2993C13.98 16.5877 14.2613 17.1414 14.2613 18.0065C14.2613 19.2407 14.25 20.2326 14.25 20.5441C14.25 20.7863 14.4188 21.0746 14.8688 20.9824C16.6554 20.364 18.2079 19.1866 19.3078 17.6162C20.4077 16.0457 20.9995 14.1611 21 12.2276C21 7.12937 16.9725 3 12 3Z\" fill=\"currentColor\"></path></svg></a>\n  </div>\n  {% endif %}\n</div> \n</div>\n"
  },
  {
    "path": "_includes/components/head.njk",
    "content": "<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>{{ renderData.title or title }} - {{ site.name }}</title>\n  <meta name=\"description\" content=\"{{ metaDescription or renderData.metaDescription or site.description }}\">\n  <link rel=\"stylesheet\" href=\"/style.css?v={% version %}\"/>\n  <link rel=\"icon\" href=\"data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>{{ site.emoji }}</text></svg>\">\n  \n  {% set js %}\n    {% include \"assets/js/inline.js\" %}\n    {% include \"assets/js/search.js\" %}\n  {% endset %}\n  \n  <script defer>{{ js | jsmin | safe }}</script>\n\n {% if site.enableNetlifyCMS == 1 %}\n  <link rel=\"dns-prefetch\" href=\"https://identity.netlify.com\">\n  <script async src=\"https://identity.netlify.com/v1/netlify-identity-widget.js\" defer></script>\n {% endif %}\n\n  {% if site.enableSearch == 1 %}\n  <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/elasticlunr/0.9.6/elasticlunr.min.js\" defer></script>\n  {% endif %}\n\n  {% if site.navigationStyle == 'horizontal' %}\n  <script src=\"https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.7.3/dist/alpine.min.js\" defer></script>\n  {% endif %}\n\n</head>\n"
  },
  {
    "path": "_includes/components/header.njk",
    "content": "<div class=\"fixed w-full top-0 left-0 z-10 \"> \n    <nav class=\"flex h-16 md:h-20 items-center bg-white dark:bg-gray-900 z-20 fixed top-0 left-0 right-0 border-b border-gray-100 px-0 py-2 dark:bg-dark dark:border-gray-800 transition-colors duration-200\">\n      <div class=\"hidden md:block space-y-4 w-full p-4\">\n        <a class=\"no-underline text-gray-600 hover:text-gray-800 font-bold dark:text-gray-500 items-center\" href=\"/\">\n          <span class=\"text-xl\">{{ site.name }}</span>\n          {% if site.subtitle %}\n          <span class=\"block mt-1 text-sm text-gray-500 hover:text-gray-600 dark:text-gray-600 font-normal text-xs sm:text-xs md:text-sm lg:text-sm w-full\"> {{ site.subtitle }}</span>\n          {% endif %}\n         </a>\n      </div>\n      <div class=\"mr-2 relative w-full md:w-64\">\n       {% if site.enableSearch == 1 %}\n        <input  aria-label=\"Search\" x-data=\"{ isOpen: true }\" x-bind:class=\"{ 'hidden': !isOpen }\" type=\"search\" placeholder=\"Search...\" class=\"ml-2 w-60 bg-gray-50 dark:bg-gray-800 appearance-none border dark:border-gray-700 rounded py-2 px-2 placeholder-gray-300 leading-tight focus:ring-4 focus:ring-blue-200 dark:focus:ring-gray-700 ring-opacity-50 border-gray-200\" id=\"searchField\">\n        <ul tabindex=\"0\" class=\"bg-white dark:bg-gray-200 z-50 shadow-md p-0 w-full list-none m-0 absolute left-0 md:right-0 bg-white rounded mt-1 top-100 z-50\" id=\"searchResults\"></ul>\n        <div class=\"hidden shadow-md list-none p-4 m-0 absolute left-0 md:right-0 bg-white rounded mt-1 border top-100 divide-y divide-gray-300 z-2\" id=\"noResultsFound\">\n          <p>No results found.</p>\n        </div>\n        {% endif %}\n      </div>\n\n      <button  aria-label=\"Show navigation\" onclick=\"showNavigation()\" class=\"block md:hidden mr-3\"><svg fill=\"none\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" class=\"text-gray-400 hover:text-gray-600\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path></svg></button>\n       \n      {% if site.enableDarkMode == 1 %}\n      <a aria-label=\"dark mode\" rel=\"noopener noreferrer\" class=\"mr-3 switch text-current cursor-pointer\" onclick=\"activateDarkMode()\"><svg stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" viewBox=\"0 0 16 16\" height=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path class=\"text-gray-400 hover:text-yellow-400 dark:text-yellow-400\" fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M11.67 8.658a3.661 3.661 0 0 0-.781 1.114 3.28 3.28 0 0 0-.268 1.329v1.6a1.304 1.304 0 0 1-.794 1.197 1.282 1.282 0 0 1-.509.102H7.712a1.285 1.285 0 0 1-.922-.379 1.303 1.303 0 0 1-.38-.92v-1.6c0-.479-.092-.921-.274-1.329a3.556 3.556 0 0 0-.776-1.114 4.689 4.689 0 0 1-1.006-1.437A4.187 4.187 0 0 1 4 5.5a4.432 4.432 0 0 1 .616-2.27c.197-.336.432-.64.705-.914a4.6 4.6 0 0 1 .911-.702c.338-.196.7-.348 1.084-.454a4.45 4.45 0 0 1 1.2-.16 4.476 4.476 0 0 1 2.276.614 4.475 4.475 0 0 1 1.622 1.616 4.438 4.438 0 0 1 .616 2.27c0 .617-.117 1.191-.353 1.721a4.69 4.69 0 0 1-1.006 1.437zM9.623 10.5H7.409v2.201c0 .081.028.15.09.212a.29.29 0 0 0 .213.09h1.606a.289.289 0 0 0 .213-.09.286.286 0 0 0 .09-.212V10.5z\"></path></svg></a>\n      {% endif %}\n\n      {% if site.enabledEncryption == 1 %} \n        <button  aria-label=\"Logout\" onclick=\"logout()\" class=\"block  mr-3\">\n        <svg  width=\"24\" height=\"24\"  xmlns='http://www.w3.org/2000/svg' class='ionicon text-gray-400 hover:text-red-800' viewBox='0 0 512 512'><title>Close Circle</title><path d='M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z' fill='none' stroke='currentColor' stroke-miterlimit='10' stroke-width='32'/><path fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32' d='M320 320L192 192M192 320l128-128'/></svg>\n        </button>\n      {% endif %}\n    </nav>  \n    {% if site.navigationStyle == 'horizontal' %}\n      <div class=\"mt-20\">\n      {% include \"components/nav.njk\" %}\n      </div>\n    {% endif %}\n </div>\n\n\n  "
  },
  {
    "path": "_includes/components/nav.njk",
    "content": "{% set navPages = collections.all | eleventyNavigation  %}\n\n{% macro renderNavListItem(entry,rel) -%}\n\n  {% if entry.url == page.url or entry.title == eleventyNavigation.parent or entry.title == eleventyComputed.key%}\n    {% if rel == \"child\" %}\n      {% set highlight = 'border-gray-600 font-semibold text-gray-500 focus:border-gray-700' %}\n    {% else %}\n      {% set highlight = 'border-gray-600 font-semibold focus:border-gray-700' %}\n    {% endif %}\n    {% set current = 'aria-current=\"page\"' %}\n  {% else %}\n    {% set highlight = 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-500 ' %}\n    {% set current = '' %}\n  {% endif %}\n \n{%- if not entry.children.length  -%}\n  {% if rel == \"child\" %}\n   <a class=\"w-max \n    rounded  \n    px-4 py-2 \n    block\n    focus:text-gray-900 \n    text-sm bg-transparent \n    dark:bg-transparent\n    dark:hover:text-gray-400 \n    md:mt-0 \n    m-0\n    hover:font-bold\n    focus:text-gray-900   \n    focus:outline-none focus:ring {{ highlight }} \n    text-gray-500 \n    dark:text-gray-500\" \n    href=\"{{ entry.url | url }}\">{{ entry.title }}</a>\n  {% else %}\n   <a class=\"w-max\n    px-4 py-3 \n    rounded \n    block\n    text-sm \n    bg-transparent \n    rounded-lg \n    dark:bg-transparent \n    dark:focus:bg-gray-600 \n    dark:focus:text-white \n    dark:hover:text-gray-500 \n    dark:text-gray-400 \n    md:mt-0 \n    hover:text-gray-900 \n    focus:text-gray-900 \n    focus:outline-none \n    focus:ring {{ highlight }} \n    text-gray-500\" \n    href=\"{{ entry.url | url }}\">{{ entry.title }}</a>\n  {% endif %}\n \n  {%- else -%}\n   \n    {%- if entry.children.length -%}\n    \n    <div @click.away=\"open = false\" class=\"relative\" x-data=\"{ open: false }\">\n        <button  @click=\"open = !open\" \n        class=\"whitespace-nowrap flex flex-row items-center w-full lg:mr-2 px-4 py-2 mt-2 text-sm text-left bg-transparent rounded-lg dark:bg-transparent dark:focus:text-white dark:hover:text-gray-400 md:w-auto md:inline md:mt-0 md:ml-4 hover:text-gray-900 hover:font-semibold focus:text-gray-900   focus:outline-none focus:ring {{ highlight }}\">\n          <span>{{ entry.title }}</span>\n          <svg fill=\"currentColor\" viewBox=\"0 0 20 20\" :class=\"{'rotate-180': open, 'rotate-0': !open}\" class=\"inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1\"><path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\"></path></svg>\n        </button>\n        <div x-show=\"open\" x-transition:enter=\"transition ease-out duration-100\" x-transition:enter-start=\"transform opacity-0 scale-95\" x-transition:enter-end=\"transform opacity-100 scale-100\" x-transition:leave=\"transition ease-in duration-75\" x-transition:leave-start=\"transform opacity-100 scale-100\" x-transition:leave-end=\"transform opacity-0 scale-95\"  x-transition=\"bg-gray-100 bg-white\" class=\"shadow bg-white absolute rounded-lg top-8 w-max ml-4 mt-2\">\n          <div class=\"py-2 w-max pr-12 dark:bg-gray-800\">\n          {%- for child in entry.children %}{{ renderNavListItem(child) }}{% endfor -%}\n          </div>\n        </div>\n      </div>\n    {%- endif -%}\n  {%- endif -%}\n{%- endmacro %}\n\n<div class=\"md:bg-white dark:bg-gray-900 p-0 mt-8 pb-8 mr-1  flex w-full justify-end\">\n  <div x-data=\"{ open: false }\" class=\"flex flex-col justify-start md:items-center  md:flex-row \">\n   \n    <nav x-ref=\"dropdown\"  :class=\" {'flex': open, 'hidden': !open}\" class=\"hidden md:block mt-4 mr-2 justify-end flex-col flex-grow pb-4 md:pb-0 hidden md:flex md:flex-row\">\n    {%- for entry in navPages %}\n    {{ renderNavListItem(entry,'child') }}\n    {%- endfor -%}\n    </nav>\n\n    <nav id=\"navigation\" class=\"md:hidden h-screen fixed inset-y-0 overflow-x-hidden overflow-y-auto  hidden w:64 lg:w-72 mt-20 md:block  dark:bg-gray-900  flex-none top-0  p-4 w-64 md:border-r border-b border-gray-100 dark:border-gray-800\">\n        <button  name=\"Close navigation\" onclick=\"closeNavigation()\" class=\"float-right justify-end block md:hidden -mr-4 p-6\">\t<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"dark:bg-gray-500\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\"><path class=\"text-gray-100\" d=\"M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z\"/></svg></button>\n        <div class=\" clear-right\">\n          <a href=\"/\">\n          <div class=\"block md:hidden pt-4 font-semibold text-gray-500\">{{ site.name }}</div>\n          <div class=\"block md:hidden text-sm text-gray-500 mb-4\">{{ site.subtitle }}</div>\n          </a>\n          {{ collections.all | eleventyNavigation | eleventyNavigationToHtml({anchorClass: \"item\",activeAnchorClass: \"active\",activeListItemClass: \"active\",activeKey: eleventyNavigation.key, listClass: \"nav\", listItemClass: \"item\"}) | safe }}\n        </div>\n      </nav>\n  </div>\n</div>\n\n\n"
  },
  {
    "path": "_includes/experimental/blog/author.njk",
    "content": "---\ntitle: Author archive\nlayout: layouts/base.njk\npagination:\n  data: collections.authors\n  size: 1\n  alias: author\npermalink: \"authors/{{ author | slug }}/\"\nrenderData:\n  author: \"{{ author }}\"\n  title: \"Posts by {{ author }}\"\n  metaDescription: \"An archive of all posts by the author: {{ author }}.\"\n---\n\n<h1>{{ renderData.title | safe }}</h1>\n\n<section>\n\t{% for post in collections.authors[author] | reverse %}\n\t\t<article{% if post.page.url == url %} data-current=\"current item\"{% endif %}>\n\t\t\t<h3>\n\t\t\t\t<a href=\"{{ post.page.url | url }}\">\n\t\t\t\t\t{% if post.title %}\n\t\t\t\t\t\t{{ post.title }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t\tUntitled\n\t\t\t\t\t{% endif %}\n\t\t\t\t</a>\n\t\t\t</h3>\n\t\t\t{% if post.summary %}\n\t\t\t\t<p>\n\t\t\t\t\t{{ post.summary }}\n\t\t\t\t</p>\n\t\t\t{% endif %}\n\t\t\t<p>\n\t\t\t\t<time datetime=\"{{ post.date | machineDate }}\">\n\t\t\t\t\t<small>{{ post.date | readableDate }} by <a href=\"/authors/{{ post.author | slug }}/\">{{ post.author }}</a></small>\n\t\t\t\t</time>\n\t\t\t</p>\n\t\t\t{% if post.tags %}\n\t\t\t\t<p>\n\t\t\t\t\t{% for tag in post.tags %}\n\t\t  \t\t\t{%- if tag != \"post\" -%}\n\t\t  \t\t\t\t{% set tagUrl %}/tags/{{ tag }}/{% endset %}\n\t\t  \t\t\t<a href=\"{{ tagUrl | url }}\" rel=\"tag\">{{ tag }}</a>\n\t\t  \t\t\t{%- endif -%}\n\t\t\t\t\t{% endfor %}\n\t\t\t\t</p>\n\t\t\t{% endif %}\n\t\t</article>\n\t{% endfor %}\n  <nav>\n    <a href=\"{{ '/authors/' | url }}\">← Authors index</a>\n  </nav>\n</section>"
  },
  {
    "path": "_includes/experimental/blog/authors.njk",
    "content": "---\ntitle: Authors\nmetaDescription: This page lists all of the Blog's authors.\nlayout: layouts/base.njk\npagination:\n  data: collections.authors\n  size: Infinity\npermalink: \"authors/index.html\"\n---\n\n<h1>{{ title }}</h1>\n\n<section>\n  {% for author in pagination.items %}\n    <article>\n      <h3>\n        <a href=\"/authors/{{ author | slug }}\">{{ author | safe }}</a>\n      </h3>\n    </article>\n  {% endfor %}\n  <nav>\n    <a href=\"{{ '/blog/' | url }}\">← Blog index</a>\n  </nav>\n</section>"
  },
  {
    "path": "_includes/experimental/blog/components/pageslist.njk",
    "content": "<section>\n\t{% for page in pageslist | reverse %}\n\t\t<article{% if post.url == url %} data-current=\"current item\"{% endif %}>\n\t\t\t<h3>\n\t\t\t\t<a href=\"{{ page.url | url }}\">\n\t\t\t\t\t{% if page.data.title %}\n\t\t\t\t\t\t{{ page.data.title }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t\tUntitled\n\t\t\t\t\t{% endif %}\n\t\t\t\t</a>\n\t\t\t</h3>\n\t\t\t{% if page.data.summary %}\n\t\t\t\t<p>\n\t\t\t\t\t{{ page.data.summary }}\n\t\t\t\t</p>\n\t\t\t{% endif %}\n\t\t\t<p>\n\t\t\t\t<time datetime=\"{{ page.date | machineDate }}\">\n\t\t\t\t\t{# <small>{{ post.date | readableDate }} by <a href=\"/authors/{{ post.data.author | slug }}/\">{{ post.data.author }}</a></small> #}\n\t\t\t\t</time>\n\t\t\t</p>\n\t\t\t{% if page.data.tags %}\n\t\t\t\t<p>\n\t\t\t\t\t{% for tag in page.data.tags %}\n\t\t  \t\t\t{%- if tag != \"post\" -%}\n\t\t  \t\t\t\t{% set tagUrl %}/tags/{{ tag }}/{% endset %}\n\t\t  \t\t\t<a href=\"{{ tagUrl | url }}\" rel=\"tag\">{{ tag }}</a>\n\t\t  \t\t\t{%- endif -%}\n\t\t\t\t\t{% endfor %}\n\t\t\t\t</p>\n\t\t\t{% endif %}\n\t\t</article>\n\t{% endfor %}\n</section>\n"
  },
  {
    "path": "_includes/experimental/blog/components/postslist.njk",
    "content": "<section>\n<ul class=\"spacelog\">\n\t{% for post in postslist | reverse %}\n\t<li>\n\t\t<time datetime=\"{{ post.date | machineDate }}\">\n\t\t<small>{{ post.date | readableDate }} — </small>\n\t\t</time>  <a href=\"{{ post.url | url }}\">\n\t\t{% if post.data.title %}\n\t\t\t{{ post.data.title }}\n\t\t{% else %}\n\t\t\tUntitled\n\t\t{% endif %}\n\t\t\t</a>\n\t\t\t{% if post.data.tags %}\n\t\t\t\t\t{% for tag in post.data.tags %}\n\t\t  \t\t\t{%- if tag != \"post\" -%}\n\t\t  \t\t\t\t{% set tagUrl %}/tags/{{ tag }}/{% endset %}\n\t\t  \t\t\t<a class=\"text-xs ml-1 px-2 py-1 text-gray-600 bg-gray-200 no-underline rounded\" href=\"{{ tagUrl | url }}\" rel=\"tag\">{{ tag }}</a>\n\t\t  \t\t\t{%- endif -%}\n\t\t\t\t\t{% endfor %}\n\t\t\t{% endif %}\n\t\t\t</li>\n\t{% endfor %}\n\t</ul>\n\t\t{% if post.data.tags %}\n\t\t\t\t<p>\n\t\t\t\t\t{% for tag in post.data.tags %}\n\t\t  \t\t\t{%- if tag != \"post\" -%}\n\t\t  \t\t\t\t{% set tagUrl %}/tags/{{ tag }}/{% endset %}\n\t\t  \t\t\t<a href=\"{{ tagUrl | url }}\" rel=\"tag\">{{ tag }}</a>\n\t\t  \t\t\t{%- endif -%}\n\t\t\t\t\t{% endfor %}\n\t\t\t\t</p>\n\t\t\t{% endif %}\n\t\t</article>\n</section>\n{# \n<h1>Foo</h1>\n{% set latest_posts = collections.posts %}\n{% for post in latest_posts.slice(0,2) | reverse %}\n{{ post.data.title}}\n{% endfor %} #}\n"
  },
  {
    "path": "_includes/experimental/blog/content/posts/firstpost.md",
    "content": "---\ntitle: This is the first example post\nmetaDescription: This is a sample meta description. If one is not present in your page/post's front matter, the default metadata.desciption will be used instead.\ndate: 2019-01-01T00:00:00.000Z\nauthor: John Appleseed\nsummary: Why contemplating our mortality can be a powerful catalyst for change\ntags:\n  - tech\n  - environment\n  - politics\n  - sport\n---\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n\nBring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.\n\n## Section Header\n\nCapitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.\n\n``` text/2-3\n// this is a command\nfunction myCommand() {\n\tlet counter = 0;\n\tcounter++;\n}\n```\nOrganically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n"
  },
  {
    "path": "_includes/experimental/blog/content/posts/fourthpost.md",
    "content": "---\ntitle: This is the fourth example post\ndate: 2020-02-03\nauthor: John Doe\nsummary: Why contemplating our mortality can be a powerful catalyst for change\ntags:\n  - environment\n  - politics\n---\nOrganically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n\n![A sample inlined image](https://source.unsplash.com/random/600x400)\n\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n"
  },
  {
    "path": "_includes/experimental/blog/content/posts/posts.json",
    "content": "{\n  \"layout\": \"layouts/post.njk\",\n  \"permalink\": \"posts/{{ title | slug }}/index.html\",\n  \"author\": \"Anonymous\",\n  \"tags\": [\n    \"post\"\n  ]\n}\n"
  },
  {
    "path": "_includes/experimental/blog/content/posts/secondpost.md",
    "content": "---\ntitle: This is the second example post\nsummary: Why contemplating our mortality can be a powerful catalyst for change\ndate: 2020-01-01\nauthor: John Appleseed\ntags:\n  - sport\n---\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n\n## Section Header\n\nBring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.\n\nCapitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.\n"
  },
  {
    "path": "_includes/experimental/blog/content/posts/the-fifth-and-hopefully-final-example-post.md",
    "content": "---\ntitle: The fifth and hopefully final example post yo yo\ndate: 2020-10-15T12:23:39.598Z\nauthor: Jane Doe\nsummary: Why contemplating our mortality can be a powerful catalyst for change\ntags:\n  - environment\n  - sport\neleventyComputed:\n  key: Spacelog \n---\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n\n![A sample inlined image](https://source.unsplash.com/random/600x400)\n\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment."
  },
  {
    "path": "_includes/experimental/blog/content/posts/thirdpost.md",
    "content": "---\ntitle: This is the third example post which has a slightly longer title than the others\ndate: 2020-01-01\nauthor: Jane Doe\nsummary: Why contemplating our mortality can be a powerful catalyst for change\ntags:\n  - tech\n  - politics\n---\nLeverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.\n\n```\npre,\ncode {\n\tline-height: 1.5;\n}\n```\n\nBring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.\n\n## Section Header\n\nCapitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.\n"
  },
  {
    "path": "_includes/experimental/blog/layouts/blog.njk",
    "content": "---\nlayout: layouts/base.njk\nsection: blog\npermalink: /blog/index.html\n---\n<div class=\"flex w-full justify-center\">\n    <div class=\"mt-4 px-6 md:px-6 lg:px-8 xl:px-12 w-full max-w-5xl\">\n        <div class=\"wrapper flex justify-between\">\n             <div class=\"main  flex flex-col pr-0 prose sm:prose lg:prose-lg xl:prose-md\">\n                <article>\n\n<h1>{{ title }}</h1>\n\n{{ layoutContent | safe }}\n\n{% set postslist = collections.post %}\n{% include \"components/postslist.njk\" %}\n </article>\n               \n            </div>    \n            \n         \n        </div>\n    </div>\n</div>\n   \n\n"
  },
  {
    "path": "_includes/experimental/blog/layouts/post.njk",
    "content": "---\nlayout: layouts/base.njk\nsection: post\n---\n{% if site.navigationStyle == \"vertical\" %}\n    {% if site.enableEditButton == true or site.enableDatestamp == true %}\n    <div class=\"flex mt-4 justify-end mr-1\">\n        {% if site.enableDatestamp == true %}\n        <div class=\"inline-block w-auto text-xs text-gray-500 pt-1 pb-1 pl-3 mr-2 rounded \">Updated <time datetime=\"{{ date | machineDate }}\">{{ date | readableDate }}</time></div>\n        {% endif %}\n        {% if site.enableEditButton == true %}\n        <div class=\"inline-block w-auto text-xs  text-gray-500 hover:bg-gray-200 pt-1 pr-4 pb-1 pl-3 rounded \"><a href=\"{{ site.githubUrl }}/edit/{{ site.githubBranch }}/{{ page.inputPath }}\">Edit</a></div>\n        {% endif %}\n    </div>\n    {% endif %}\n{% endif %}\n \n<div class=\"flex w-full justify-center\">\n    <div class=\"mt-4 px-6 md:px-6 lg:px-8 xl:px-12 w-full max-w-5xl\">\n        <div class=\"wrapper flex justify-between\">\n            {% if site.enableTOC and toc %} \n            <div class=\"main flex flex-col pr-0 xl:pr-64 prose sm:prose lg:prose-lg xl:prose-md\">\n            {% else %}\n             <div class=\"main  flex flex-col pr-0 prose sm:prose lg:prose-lg xl:prose-md\">\n            {% endif %}    \n                <article>\n                <h1 class=\"dark:text-gray-500\">{{ title }}</h1>\n                {% if site.navigationStyle == \"horizontal\" %}\n                    {% if site.enableEditButton == true or site.enableDatestamp == true %}\n                        <div class=\"flex mt-4 justify-end mr-1\">\n                        {% if site.enableDatestamp == true %}\n                            <div class=\"inline-block w-auto text-xs text-gray-500 pt-1 pb-1 pl-3 mr-2 rounded \">Updated <time datetime=\"{{ date | machineDate }}\">{{ date | readableDate }}</time></div>\n                        {% endif %}\n                        {% if site.enableEditButton == true %}\n                            <div class=\"inline-block w-auto text-xs  text-gray-500 hover:bg-gray-200 pt-1 pr-4 pb-1 pl-3 rounded \"><a class=\"text-gray-500 no-underline font-normal !important\" href=\"{{ site.githubUrl }}/edit/{{ site.githubBranch }}/{{ page.inputPath }}\">Edit</a></div>\n                        {% endif %}\n                        </div>\n                    {% endif %}\n                {% endif %}\n                <div class=\"adjust dark:text-gray-400\">\n                    {{ layoutContent | safe }}\n                    {% if (site.enableComments) and (comments !== 0) %}\n                        <!-- Paste your comment code here! -->\n                    {% endif %}\n                    \n                   {% if tags %}\n    <p>\n    {% for tag in tags %}\n      {%- if tag != \"post\" -%}\n        {% set tagUrl %}/tags/{{ tag }}/{% endset %}\n        <a class=\"text-xs px-3 py-2 text-gray-600 bg-gray-200 no-underline rounded\" href=\"{{ tagUrl | url }}\" rel=\"tag\">{{ tag }}</a>\n      {%- endif -%}\n    {% endfor %}\n    </p>\n  {% endif %}\n\n<hr />\n  {% if nextPost.url %}\n    <p class=\"ctr\">\n      <strong>Next</strong>: \n      <a class=\"next\" href=\"{{ nextPost.url }}\">{{ nextPost.data.title }}</a>\n    </p>\n  {% endif %}\n  {% if prevPost.url %}\n    <p class=\"ctr\">\n      <strong>Previous</strong>: \n      <a class=\"previous\" href=\"{{ prevPost.url }}\">{{ prevPost.data.title }}</a>\n    </p>\n  {% endif %}\n<nav>\n  <a href=\"{{ '/blog/' | url }}\">← Spacelog</a>\n</nav>\n\n                </div>\n                </article>\n            </div>    \n            \n        </div>\n    </div>\n</div>\n "
  },
  {
    "path": "_includes/experimental/blog/pages/blog.md",
    "content": "---\nlayout: layouts/blog.njk\ntitle: Spacelog \ndate: 2020-12-21\npermalink: /blog/index.html\neleventyNavigation:\n  key: Spacelog\n  order: 200\n---"
  },
  {
    "path": "_includes/experimental/blog/tags.njk",
    "content": "---\npagination:\n  data: collections\n  size: 1\n  alias: tag\n  filter:\n    - all\n    - nav\n    - post\n    - posts\n    - page\n    - pages\npermalink: /tags/{{ tag }}/\nlayout: layouts/base.njk\nrenderData:\n  title: {{ tag }}\n  metaDescription: \"All content tagged with “{{ tag }}”\"\n---\n<div class=\"flex w-full justify-center\">\n    <div class=\"mt-4 px-6 md:px-6 lg:px-8 xl:px-12 w-full max-w-5xl\">\n        <div class=\"wrapper flex justify-between\">\n             <div class=\"main  flex flex-col pr-0 prose sm:prose lg:prose-lg xl:prose-md\">\n<h1>Tagged: {{ tag }}</h1>\n\n{% set postslist = collections[tag] %}\n{% include \"components/postslist.njk\" %}\n\n<nav>\n  <a href=\"{{ '/blog/' | url }}\">← Blog index</a>\n</nav>\n\n </div>    \n            \n         \n        </div>\n    </div>\n</div>\n   \n\n"
  },
  {
    "path": "_includes/layouts/404.njk",
    "content": "<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{{ title }}</title>\n       {% set css %}\n    {% include \"_includes/assets/css/404.css\" %}\n  {% endset %}\n  <style>{{ css | cssmin | safe }}</style>\n     {% set js %}\n    {% include \"_includes/assets/js/404.js\" %}\n  {% endset %}\n  <script>{{ js | jsmin | safe }}</script> \n<div class=\"moon\"></div>\n<div class=\"moon__crater moon__crater1\"></div>\n<div class=\"moon__crater moon__crater2\"></div>\n<div class=\"moon__crater moon__crater3\"></div>\n\n<div class=\"star star1\"></div>\n<div class=\"star star2\"></div>\n<div class=\"star star3\"></div>\n<div class=\"star star4\"></div>\n<div class=\"star star5\"></div>\n\n<div class=\"error\">\n  <div class=\"error__title\">404</div>\n  <div class=\"error__subtitle\">Ground Control to Major Tom</div>\n  <div class=\"error__description\">Your circuit's dead, there's something wrong</div>\n  <a href=\"/\"><button class=\"error__button error__button--active\">Go home</button></a>\n</div>\n\n<div class=\"astronaut\">\n  <div class=\"astronaut__backpack\"></div>\n  <div class=\"astronaut__body\"></div>\n  <div class=\"astronaut__body__chest\"></div>\n  <div class=\"astronaut__arm-left1\"></div>\n  <div class=\"astronaut__arm-left2\"></div>\n  <div class=\"astronaut__arm-right1\"></div>\n  <div class=\"astronaut__arm-right2\"></div>\n  <div class=\"astronaut__arm-thumb-left\"></div>\n  <div class=\"astronaut__arm-thumb-right\"></div>\n  <div class=\"astronaut__leg-left\"></div>\n  <div class=\"astronaut__leg-right\"></div>\n  <div class=\"astronaut__foot-left\"></div>\n  <div class=\"astronaut__foot-right\"></div>\n  <div class=\"astronaut__wrist-left\"></div>\n  <div class=\"astronaut__wrist-right\"></div>\n  \n  <div class=\"astronaut__cord\">\n    <canvas id=\"cord\" height=\"500px\" width=\"500px\"></canvas>\n  </div>\n  \n  <div class=\"astronaut__head\">\n    <canvas id=\"visor\" width=\"60px\" height=\"60px\"></canvas>\n    <div class=\"astronaut__head-visor-flare1\"></div>\n    <div class=\"astronaut__head-visor-flare2\"></div>\n  </div>\n</div>\n  </body>\n</html>\n"
  },
  {
    "path": "_includes/layouts/base.njk",
    "content": "<!doctype html>\n<html {% if section %} data-current=\"{{ section }}\"{% endif %} lang=\"en\">\n  {% include \"components/head.njk\" %}\n  <body>\n    <div id=\"app\" class=\"h-screen bg-white dark:bg-gray-900\">\n      {% include \"components/header.njk\" %}\n      {% if site.navigationStyle == \"vertical\" %}\n      <nav id=\"navigation\" class=\"fixed inset-y-0 overflow-x-hidden overflow-y-auto  hidden w:64 lg:w-72 mt-20 md:block  dark:bg-gray-900  flex-none top-0  p-4 w-64 md:border-r border-b border-gray-100 dark:border-gray-800\">\n        <button  name=\"Close navigation\" onclick=\"closeNavigation()\" class=\"float-right justify-end block md:hidden -mr-4 p-6\">\t<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"dark:bg-gray-500\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\"><path class=\"text-gray-100\" d=\"M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z\"/></svg></button>\n        <div class=\" clear-right\">\n          <a href=\"/\">\n          <div class=\"block md:hidden pt-4 font-semibold text-gray-500\">{{ site.name }}</div>\n          <div class=\"block md:hidden text-sm text-gray-500 mb-4\">{{ site.subtitle }}</div>\n          </a>\n          {{ collections.all | eleventyNavigation | eleventyNavigationToHtml({anchorClass: \"item\",activeAnchorClass: \"active\",activeListItemClass: \"active\",activeKey: eleventyNavigation.key, listClass: \"nav\", listItemClass: \"item\"}) | safe }}\n        </div>\n      </nav>\n      {% endif %}\n      {% if site.navigationStyle == 'horizontal' %}\n        <main id=\"main\" class=\"dark:bg-gray-900 pt-16 sm:pt-18 md:pt-48\">\n      {% else %}\n        <main id=\"main\" class=\"dark:bg-gray-900 pt-16 sm:pt-18 md:pt-20 md:pl-64 lg:pl-72\">\n      {% endif %}     \n        {{ layoutContent | safe }} \n        {% include \"components/footer.njk\" %} \n        </main>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_includes/layouts/contact.njk",
    "content": "---\nlayout: layouts/base.njk\nsection: contact\n---\n<div class=\"prose prose-sm sm:prose lg:prose-lg xl:prose-xl mt-8 pl-4 pr-4\">\n{% include \"components/contact.njk\" %}\n</div>"
  },
  {
    "path": "_includes/layouts/page.njk",
    "content": "---\nlayout: layouts/base.njk\nsection: page\n---\n\n{% if site.navigationStyle == \"vertical\" %}\n    {% if site.enableEditButton == true or site.enableDatestamp == true %}\n    <div class=\"flex mt-4 justify-end mr-1\">\n        {% if site.enableDatestamp == true %}\n        <div class=\"inline-block w-auto text-xs text-gray-500 pt-1 pb-1 pl-3 mr-2 rounded \">Updated <time datetime=\"{{ page.date | machineDate }}\">{{ page.date | readableDate }}</time></div>\n        {% endif %}\n        {% if site.enableEditButton == true %}\n        <div class=\"inline-block w-auto text-xs  text-gray-500 hover:bg-gray-200 pt-1 pr-4 pb-1 pl-3 rounded \"><a target=\"_blank\" rel=\"noopener\" rel=\"noreferrer\" href=\"{{ site.githubUrl }}/edit/{{ site.githubBranch }}/{{ page.inputPath }}\">Edit</a></div>\n        {% endif %}\n    </div>\n    {% endif %}\n{% endif %}\n \n<div class=\"flex w-full justify-center\">\n    <div class=\"mt-4 px-6 md:px-6 lg:px-8 xl:px-12 w-full max-w-5xl\">\n        <div class=\"wrapper flex justify-between\">\n            {% if site.enableTOC and toc %} \n            <div class=\"main flex flex-col pr-0 xl:pr-64 prose sm:prose lg:prose-lg xl:prose-md\">\n            {% else %}\n             <div class=\"main  flex flex-col pr-0 prose sm:prose lg:prose-lg xl:prose-md\">\n            {% endif %}    \n                <article>\n                <h1 class=\"dark:text-gray-500\">{{ title }}</h1>\n                {% if site.navigationStyle == \"horizontal\" %}\n                    {% if site.enableEditButton == true or site.enableDatestamp == true %}\n                        <div class=\"flex mt-4 justify-end mr-1\">\n                        {% if site.enableDatestamp == true %}\n                            <div class=\"inline-block w-auto text-xs text-gray-500 pt-1 pb-1 pl-3 mr-2 rounded \">Updated <time datetime=\"{{ page.date | machineDate }}\">{{ page.date | readableDate }}</time></div>\n                        {% endif %}\n                        {% if site.enableEditButton == true %}\n                            <div class=\"inline-block w-auto text-xs  text-gray-500 hover:bg-gray-200 pt-1 pr-4 pb-1 pl-3 rounded \"><a class=\"text-gray-500 no-underline font-normal !important\" target=\"_blank\" href=\"{{ site.githubUrl }}/edit/{{ site.githubBranch }}/{{ page.inputPath }}\">Edit</a></div>\n                        {% endif %}\n                        </div>\n                    {% endif %}\n                {% endif %}\n                <div class=\"self-center adjust  dark:text-gray-400\">\n                    {{ layoutContent | safe }}\n                    {% if (site.enableComments) and (comments !== 0) %}\n                        <!-- Paste your comment code here! -->\n                    {% endif %}\n                    \n                    {% if site.enablePageNavigation == true %}\n                     <ul class=\"footer-nav pt-4 mb-8  ml-0 pl-0 flex flex-wrap flex-row-reverse  justify-between mt-8 list-none\">\n                     {%- set nextPage = collections.menuItems | getNextCollectionItem(page) %}\n                     {%- if nextPage %}<li class=\"ml-0 pl-0\"><a class=\"font-semibold text-gray-500 hover:text-gray-900\" href=\"{{ nextPage.url | url }}\">{% if nextPage.data.eleventyNavigation.title %}{{  nextPage.data.eleventyNavigation.title }}{% else %}{{  nextPage.data.eleventyNavigation.key }}{% endif %}</a> <svg height=\"24\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"#6B7280\" class=\"inline ml-1 flex-shrink-0\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path></svg></li>{% endif %}\n                     {%- set previousPage = collections.menuItems | getPreviousCollectionItem(page) %}\n                     {%- if previousPage %}<li class=\"ml-0 pl-0\"><svg height=\"24\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"#6B7280\" class=\"transform rotate-180 inline mr-1 flex-shrink-0\">\n                     <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"></path></svg>\n                     <a class=\"font-semibold text-gray-500 hover:text-gray-900\" href=\"{{ previousPage.url | url }}\">\n                    {% if previousPage.data.eleventyNavigation.title %}{{  previousPage.data.eleventyNavigation.title }}{% else %}{{  previousPage.data.eleventyNavigation.key }}{% endif %} </a> </li>{% endif %}\n                    </ul>\n                    {% endif %}\n                </div>\n                </article>\n            </div>    \n            \n            {% if site.enableTOC and toc %}\n            <div class=\"text-gray-500 font-semibold hidden xl:block sidebar sticky right-0 mt-12 -ml-56 w-56 h-full top-48\">\n            <small>ON THIS PAGE</small><br />\n                <aside class=\"font-normal\">\n                {{ content | toc | safe }}\n                </aside>\n            </div>\n            {% endif %}\n        </div>\n    </div>\n</div>\n   \n\n"
  },
  {
    "path": "_includes/layouts/robots.njk",
    "content": "User-agent: * Disallow: /"
  },
  {
    "path": "admin/config.yml",
    "content": "backend:\n  name: git-gateway\n  branch: main # Branch to update (optional; defaults to main)\n\n# Uncomment below to enable drafts\n# publish_mode: editorial_workflow\n\nmedia_folder: \"static/img\" # Media files will be stored in the repo under images/uploads\n\n# # Cloudinary\n# media_library:\n#   name: cloudinary\n#   config:\n#     cloud_name: broeker\n#     api_key: 159818251742281\n\ncollections:\n  # Our blog posts\n  # - name: \"blog\" # Used in routes, e.g., /admin/collections/blog\n  #   label: \"Post\" # Used in the UI\n  #   folder: \"posts\" # The path to the folder where the documents are stored\n  #   create: true # Allow users to create new documents in this collection\n  #   slug: \"{{slug}}\" # Filename template, e.g., YYYY-MM-DD-title.md\n  #   fields: # The fields for each document, usually in front matter\n  #     - { label: \"Title\", name: \"title\", widget: \"string\" }\n  #     - { label: \"Publish Date\", name: \"date\", widget: \"datetime\" }\n  #     - { label: \"Author\", name: \"author\", widget: \"string\", default: \"Anonymous\" }\n  #     - { label: \"Summary\", name: \"summary\", widget: \"text\" }\n  #     - { label: \"Tags\", name: \"tags\", widget: \"list\", default: [\"post\"] }\n  #     - { label: \"Body\", name: \"body\", widget: \"markdown\" }\n  # Our pages e.g. About\n  - name: \"pages\"\n    label: \"Page\"\n    folder: \"pages\"\n    create: true # Change to true to allow editors to create new pages\n    slug: \"{{slug}}\"\n    fields:\n      - { label: \"Title\", name: \"title\", widget: \"string\" }\n      - { label: \"Publish Date\", name: \"date\", widget: \"datetime\" }\n      - { label: \"Permalink\", name: \"permalink\", widget: \"string\" }\n      - label: \"Navigation\" # https://www.11ty.dev/docs/plugins/navigation/\n        name: \"eleventyNavigation\"\n        widget: \"object\"\n        fields:\n          - { label: \"Key\", name: \"key\", widget: \"string\" }\n          - { label: \"Order\", name: \"order\", widget: \"number\", default: 100 }\n          - { label: \"Parent\", name: \"parent\", widget: \"string\", required: false, hint: \"(Optional) Enter a matching parent key to set this a nested or child page\" }\n          - { label: \"Title\", name: \"title\", widget: \"string\",  required: false, hint: \"(Optional) Enter alternate text for navigation link\" }\n      - { label: \"Body\", name: \"body\", widget: \"markdown\" }\n  - label: \"Globals\"\n    name: \"globals\"\n    files:\n      - label: \"Site Data\"\n        name: \"site_data\"\n        delete: false\n        file: \"_data/site.json\"\n        fields:\n          - {label: \"Site name\", name: \"name\", widget: \"string\"}\n          - {label: \"Site subtitle\", name: \"subtitle\", widget: \"string\", required: false}\n          - {label: \"Meta description\", name: \"description\", widget: \"string\"}\n          - {label: \"Site footer\", name: \"footer\", widget: \"string\", required: false}\n          - {label: \"Site Url\", name: \"url\", widget: \"string\"}\n          - {label: \"Github Url\", name: \"githubUrl\", widget: \"string\"}\n          - {label: \"Github branch\", name: \"githubBranch\", widget: \"string\"}\n          - {label: \"Navigation style\", name: \"navigationStyle\", widget: \"string\"}\n          - {label: \"Site emoji\", name: \"emoji\", widget: \"string\", required: false}\n          - {label: \"Enable search\", name: \"enableSearch\", widget: \"boolean\"}\n          - {label: \"Enable darkmode\", name: \"enableDarkMode\", widget: \"boolean\"}\n          - {label: \"Enable edit button\", name: \"enableEditButton\", widget: \"boolean\"}\n          - {label: \"Enable datestamp\", name: \"enableDatestamp\", widget: \"boolean\"}\n          - {label: \"Enable Github link\", name: \"enableGithubLink\", widget: \"boolean\"}\n          - {label: \"Enable contact form\", name: \"enableContact\", widget: \"boolean\"}\n          - {label: \"Enable Netlify CMS\", name: \"enableNetlifyCMS\", widget: \"boolean\", default: false}\n          - {label: \"Enable comments\", name: \"enableComments\", widget: \"boolean\", default: false}\n          - {label: \"Enable encryption\", name: \"enableEncryption\", widget: \"boolean\", default: false}\n          - {label: \"Enable page navigation\", name: \"enablePageNavigation\", widget: \"boolean\", default: false}"
  },
  {
    "path": "admin/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Netlify CMS</title>\n  </head>\n  <body>\n    <!-- Include the script that builds the page and powers Netlify CMS -->\n    <script src=\"https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js\"></script>\n    <!-- Include Netlify Identity for authentication -->\n    <script src=\"https://identity.netlify.com/v1/netlify-identity-widget.js\"></script>\n    <script type=\"module\" src=\"/admin/preview-templates/index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "admin/preview-templates/index.js",
    "content": "import Page from \"/admin/preview-templates/page.js\";\n// import Post from \"/admin/preview-templates/post.js\";\n\n// Register the Post component as the preview for entries in the blog collection\nCMS.registerPreviewTemplate(\"pages\", Page);\n// CMS.registerPreviewTemplate(\"blog\", Post);\n\nCMS.registerPreviewStyle(\"/style.css\");\n\n// Register any CSS file on the home page as a preview style\n// fetch(\"/\")\n//   .then(response => response.text())\n//   .then(html => {\n//     const f = document.createElement(\"html\");\n//     f.innerHTML = html;\n//     Array.from(f.getElementsByTagName(\"link\")).forEach(tag => {\n//       if (tag.rel == \"stylesheet\" && !tag.media) {\n//         CMS.registerPreviewStyle(tag.href);\n//       }\n//     });\n//   });\n"
  },
  {
    "path": "admin/preview-templates/page.js",
    "content": "import htm from \"https://unpkg.com/htm?module\";\n\nconst html = htm.bind(h);\n\n// Preview component for a Page\nconst Page = createClass({\n  render() {\n    const entry = this.props.entry;\n\n    return html`\n      <main class=\"prose p-4\">\n        <h1>${entry.getIn([\"data\", \"title\"], null)}</h1>\n        <div class=\"adjust\">\n        ${this.props.widgetFor(\"body\")}\n        </div>\n      </main>\n    `;\n  }\n});\n\nexport default Page;\n"
  },
  {
    "path": "admin/preview-templates/post.js",
    "content": "import htm from \"https://unpkg.com/htm?module\";\nimport format from \"https://unpkg.com/date-fns@2.7.0/esm/format/index.js?module\";\n\nconst html = htm.bind(h);\n\n// Preview component for a Post\nconst Post = createClass({\n  render() {\n    const entry = this.props.entry;\n\n    return html`\n      <main class=\"prose p-4\">\n        <article>\n          <h1>${entry.getIn([\"data\", \"title\"], null)}</h1>\n          <div class=\"inline-block w-auto text-xs text-gray-500 pt-1 pb-1 pl-3 mr-2 rounded \">Updated <time datetime=\"{{ date | machineDate }}\">{{ date | readableDate }}</time></div>\n          <p>${entry.getIn([\"data\", \"summary\"], \"\")}</p>\n          <div class=\"adjust\">\n          ${this.props.widgetFor(\"body\")}\n          </div>\n          <p>\n            ${\n              entry.getIn([\"data\", \"tags\"], []).map(\n                tag =>\n                  html`\n                    <a class=\"text-xs mr-2 px-3 py-2 text-gray-600 bg-gray-200 no-underline rounded\" href=\"#\" rel=\"tag\">${tag}</a>\n                  `\n              )\n            }\n          </p>\n        </article>\n      </main>\n    `;\n  }\n});\n\nexport default Post;\n"
  },
  {
    "path": "content/buy.md",
    "content": "---\npermalink: false\neleventyNavigation:\n  key: Get the eBook edition\n  order: 10\n  url: https://leanpub.com/proseforprogrammers\n---"
  },
  {
    "path": "content/pages/contact.md",
    "content": "---\nlayout: layouts/contact.njk\ntitle: Send a message \nsection: contact\ndate: Last Modified\npermalink: /contact/index.html\n---\nYou can use [Netlify Forms](https://www.netlify.com/docs/form-handling/) to create contact forms like this one, or any other custom forms you may wish to create. All submissions are sent directly to your Netlify dashboard (with optional notifications.) All forms utilize Netlify's native spam filter will display a CAPTCHA for any flagged submissions.\n"
  },
  {
    "path": "content/pages/home.md",
    "content": "---\ntitle: About this book\npermalink: /\neleventyNavigation:\n  key: About this book\n  order: 0\n---\n\n_Prose for Programmers_ is a book for programmers.\nIt is a guide to mastering the most difficult programming language of all: human language.\n\nJust as with programming,\nwe write with particular goals in mind.\nThat goal might be as simple as reminding someone about a requirement\nor as complex as justifying an entirely new architecture for a product.\nBut in every case we write in order to achieve something.\n\nThis book will teach you how to achieve those goals more effectively with clearer, more persuasive writing.\n\n## It is a work in progress\n\nThe first three chapters are content complete.\n\n* [Why should developers study writing?](/manuscript/why)\n* [General Rules](/manuscript/rules)\n* [The Writing Process](/manuscript/process)\n\nAnd there are four chapters to come.\n\n* Writing Structures\n* Audience\n* Genres\n* Other Resources\n\n## It is editable on GitHub\n\nThe manuscript of _Prose for Programmers_,\nas well as the code for the website is hosted on [GitHub](https://github.com/joshuacc/prose-for-programmers).\nEach chapter has a convenient edit link at the top of the page.\nIf you see any mistakes, typos, or other issues,\nfeel free to edit and open a pull request.\n\n## It is available in eBook form for your Kindle or other e-reader\n\nYou can get the EPUB/MOBI/PDF version of _Prose for Programmers_ [via Leanpub](https://leanpub.com/proseforprogrammers)."
  },
  {
    "path": "content/pages/pages.json",
    "content": "{\n  \"layout\": \"layouts/page.njk\"\n}\n"
  },
  {
    "path": "filters/searchFilter.js",
    "content": "const elasticlunr = require(\"elasticlunr\");\nconst emojiRegex = require('emoji-regex/RGI_Emoji.js')\n\nmodule.exports = function (collection) {\n  // what fields we'd like our index to consist of\n  var index = elasticlunr(function () {\n    this.addField(\"title\");\n    this.addField(\"content\");\n    this.setRef(\"id\");\n  });\n\n  // loop through each page and add it to the index\n  collection.forEach((page) => {\n    index.addDoc({\n      id: page.url,\n      title: page.template.frontMatter.data.title,\n      content: squash(page.templateContent),\n    });\n  });\n  \n  function squash(text) {\n    const regex = emojiRegex();\n    var content = new String(text);\n\n    // all lower case, please\n    var content = content.toLowerCase();\n  \n    // remove all html elements and new lines\n    var re = /(.*?&lt;.*?&gt;)/gi;\n    var plain = unescape(content.replace(re, ''));\n  \n    // remove duplicated words\n    var words = plain.split(' ');\n    var deduped = [...(new Set(words))];\n    var dedupedStr = deduped.join(' ')\n  \n    // remove short and less meaningful words\n    var result = dedupedStr.replace(/\\b(\\.|\\,|\\<;|the|a|an|and|am|you|I|to|if|of|off|me|my|on|in|it|is|at|as|we|do|be|has|but|was|so|no|not|or|up|for)\\b/gi, '');\n    //remove newlines, and punctuation\n    result = result.replace(/\\.|\\,|\\?|<p>|-|—|\\n/g, '');\n    //remove repeated spaces\n    result = result.replace(/[ ]{2,}/g, ' ');\n    // remove most emoji\n    result = result.replace(/([#0-9]\\u20E3)|[\\xA9\\xAE\\u203C\\u2047-\\u2049\\u2122\\u2139\\u3030\\u303D\\u3297\\u3299][\\uFE00-\\uFEFF]?|[\\u2190-\\u21FF][\\uFE00-\\uFEFF]?|[\\u2300-\\u23FF][\\uFE00-\\uFEFF]?|[\\u2460-\\u24FF][\\uFE00-\\uFEFF]?|[\\u25A0-\\u25FF][\\uFE00-\\uFEFF]?|[\\u2600-\\u27BF][\\uFE00-\\uFEFF]?|[\\u2900-\\u297F][\\uFE00-\\uFEFF]?|[\\u2B00-\\u2BF0][\\uFE00-\\uFEFF]?|(?:\\uD83C[\\uDC00-\\uDFFF]|\\uD83D[\\uDC00-\\uDEFF])[\\uFE00-\\uFEFF]?/g, '');\n   \n    let match;\n    while (match = regex.exec(result)) {\n      const emoji = match[0];\n      result = result.replace(emoji,' ')\n    }\n  \n    return result;\n  }\n\n  return index.toJSON();\n};"
  },
  {
    "path": "loader.js",
    "content": "if (localStorage.getItem('password')) {\n    insertPlainHTML(atob(localStorage.getItem('password')))\n} else {\n    document.getElementById('staticrypt-form').addEventListener('submit', function(e) {\n        e.preventDefault();\n        insertPlainHTML(document.getElementById('staticrypt-password').value);\n    });\n}"
  },
  {
    "path": "manuscript/Book.txt",
    "content": "why.md\nrules.md\nprocess.md"
  },
  {
    "path": "manuscript/manuscript.json",
    "content": "{\n  \"layout\": \"layouts/page.njk\"\n}\n"
  },
  {
    "path": "manuscript/process.json",
    "content": "{\n  \"title\": \"The Writing Process\",\n  \"eleventyNavigation\": {\n    \"key\": \"The Writing Process\",\n    \"order\": 3\n  }\n}"
  },
  {
    "path": "manuscript/process.md",
    "content": "# The Writing Process\n\nMany people are under the impression that writing is a mystical\n-- or at least mysterious --\nactivity, governed entirely by inspiration.\nWhile it is true that some authors work this way,\nwaiting for inspiration to strike isn't a common strategy among professional writers,\neven novelists.\n\nFor programmers and others writing non-fiction in a business context,\nthere is a simple process that yields quality results.\n\n1. Determine the goal\n2. Determine the audience\n3. Choose a suitable structure\n4. Build an outline\n5. Turn the outline into prose\n6. Revise obvious weaknesses\n7. Obtain feedback\n8. Revise based on feedback\n9. Publish\n\nIn this chapter, we will walk through what each of these steps entail.\n\n## 1. Determine the Goal\n\n### Why am I writing this, anyway?\n\nEvery time you start writing something,\nask yourself, \"Why?\"\nSometimes the answer is obvious,\nbut often it's not.\nAnd even on those occasions when it is obvious,\nasking the question helps keep you focused on the goal.\n\nIt's important to remember that we're trying to find the purpose of the document,\nnot your personal motivation for writing it.\nIf your answer to \"Why am I writing this?\" includes the words \"I\" or \"me,\"\nit is worth evaluating whether you're really thinking of the document's goal.\n\nFor instance, if the answer to why you are writing a tutorial is,\n\"So that I can get a raise,\"\nyou're thinking of the wrong thing.\nIt's not that the motivation is _wrong_.\nIt's just _irrelevant_ to producing a good tutorial.\nA better answer is,\n\"To help others improve their game's performance.\"\n\nBecause this answer is focused on what the audience receives,\nit is actually useful for guiding your writing efforts.\n\n### Keep asking why.\n\nOften, the first goal we come up with will be superficial.\n\"Teaching others how to use object pools,\"\nmay be accurate,\nand even somewhat useful,\nbut a bit more context can be even more useful.\n\nThere is a technique for root cause analysis called [5 Whys][],\nthe premise of which is that you need to ask \"Why?\" multiple times to find the root cause of a problem.\nThis technique also works well for determining a useful goal for writing.\n\nSuppose the first goal that occurs to you is\n\"Teach developers how to use object pools.\"\nThat is a perfectly clear and useful goal.\nBut if you write only to that narrow goal,\nyour readers won't know why the technique is useful.\nSo ask yourself, \"Why object pools?\"\n\nPerhaps the answer is \"To improve performance.\"\nBut again we can ask \"Why?\"\nAnd our answer is something like, \"To keep gameplay smooth.\"\n\nAt this point we can state the goal as:\n\"Teach game developers how to keep their games running smoothly by using object pools.\"\n\nWith this more robust goal in mind we're more likely to communicate,\nnot just the technique,\nbut also its importance and trade-offs.\n\n## 2. Determine the Audience\n\nOnce we understand the goal of the document,\nwe have enough information to start considering our audience.\nOur first question, though, takes a step back from the goal.\n\n### Who will be reading this?\n\nOften the readership of documents is wider than we would initially expect.\nA framework's website will be read by developers, of course,\nbut perhaps also:\n\n* Architects evaluating technology choices\n* Managers trying to keep abreast of what their team is using\n* Technical recruiters trying to understand the skillset they are hiring for\n* Designers trying to understand technical constraints on their designs\n* Sysadmins figuring out the framework's deployment features\n\nTake time to list the different types of potential readers.\nDoing so will help draw out whether additional supporting material is needed.\n\n### Which readers are primary?\n\nOnce you have the list of potential readers,\nrefer back to the goal to decide which readers are most important.\nIn most cases there will be a single group of readers who constitute your primary audience.\n\nContinuing the previous example:\nthe primary audience of a framework website is developers.\nOthers are important, but secondary to that audience.\n\n### What is their relation to the subject?\n\nAt this point we have our primary audience,\nbut haven't given much detail about them.\nSo it's time to consider their relation to the subject.\n\nOne important axis to consider is their current level of expertise.\nAre they absolute beginners,\nworld class experts,\nor somewhere in between?\nThe answer to this question drives\nwhich sorts of things can be assumed\nand which need to be explained in great detail.\n\nAnother axis is the readers emotional relationship with the subject.\nAre they intimidated, enthusiastic, or something else?\nA developer who fled Java for Ruby will have a very different attitude toward Haskell than a brand new developer.\nThey may both be fearful,\nbut about different things.\nThose emotional concerns also need to be addressed.\n\n### What is their relation to you?\n\nIn addition to the subject,\nwe must also consider how the audience is related to you,\nthe author.\nAre they coworkers?\nThen you can make certain assumptions about their familiarity with the business.\n\nAre you on friendly terms or is some of the audience hostile?\nYou may need to focus more on your logical case for the latter.\n\nAre you part of the same culture/subculture?\n\"Corporate suits\" probably won't find image macros as amusing as your 22-year-old developer buddy.\n\n[5 Whys]: http://en.wikipedia.org/wiki/5_Whys\n\n## 3. Choose a Suitable Structure\n\nNow that we know the goal and the audience\nwe can consider how to structure the document to serve them.\n\n### Choosing a structure based on the goal\n\nGoals can generally be placed on a spectrum between purely informational and purely persuasive.\nOn one end of the spectrum,\ntopical hierarchies are great at communicating lots of information efficiently.\nThe hierarchy conveys the big picture while also supporting scanning through subtopics.\n\nAt the other end of the spectrum,\nnarrative is particularly effective at persuading people by engaging our natural sense of empathy.\nTelling a child that \"Lying is a bad idea,\" is less likely to change their behavior than hearing _The Boy Who Cried Wolf_.\nFor an example closer to our industry, consider _The Phoenix Project_:\nit vividly illustrates the problems of bureacratic IT departments\nas well as the benefits of embracing the DevOps movement.\n\n### Choosing a structure based on the audience\n\nYour structure also needs to be suited to your audience.\n\nIf your primary audience is developers with deep experience in your topic,\nthen you may want to address them with an equally deep and detailed hierarchy of topics.\nA beginner, however, would likely benefit from a shallower step by step \"recipe\" guide.\n\nThe reader's level of interest factors into which structure is best suited.\nA highly motivated reader may want to get right to the heart of the matter.\nBut a distinterested reader\n--who is only looking at your document because his boss made him--\nmay need to be enticed with a joke or anecdote explaining what is in it for him.\nThat sort of reader will probably also need frequent positive reinforcement.\n\nThe audience's relationship with you also makes a difference.\nIf they are familiar with you and trust your judgment,\nthey are more likely to be patient waiting for a payoff.\nBut if they don't know anything about you,\nthe internet is only a click away.\n\n### Mixing and matching\n\nMost writing structures are relatively flexible\nand can be combined with other structures as warranted by the goal and the audience.\n**Don't be afraid to mix and match them.**\n\nFor example, suppose that you need to convince business leaders that\nit is worthwhile to break your large monolithic application into several separate services.\nYou'd probably start with a Problem-Solution structure like this:\n\n* Problems with the current architecture\n* Proposed solution\n\nIn order to help the businesspeople make a decision, you'd probably extend it with a Pro-Con analysis as well.\n\n* Problems with the current architecture\n* Proposed solution\n* Costs and risks of change\n* Costs and risks of not changing\n\nA simple factual elaboration on that outline may win intellectual assent,\nbut is unlikely to elicit wholehearted support from non-technical leaders.\nWhy?\nBecause they lack experiential knowledge of the problems, solutions, and risks.\n\nBut parables and other metaphorical narratives can impart a degree of experiential knowledge without requiring actual experience.\nWhat sort of narrative would work in this case?\n\nPerhaps a story of a military building a single gigantic ship.\nIt is powerful,\nbut difficult to maneuver,\nand if it somehow fails then its entire arsenal is useless.\n(Business books are fond of military metaphors for some reason.)\nThen contrast this with building a fleet of small independently maneuverable ships.\n\nRevising the outline to incorporate this narrative gives us:\n\n* Problems with the current architecture\n    * Parable of the dreadnought\n    * Supporting factual details\n* Proposed solution\n    * Parable of the fleet\n    * Supporting factual details\n* Costs and risks of change\n    * Refer to parable\n    * Supporting factual details\n* Costs and risks of not changing\n    * Refer to parable\n    * Supporting factual details\n\nCombining these three structures creates a much more powerful and persuasive account than any of them alone.\n\n## 4. Build an Outline\n\nWith a structure\n(or set of structures)\nchosen for your project,\nit is time to build an outline.\nSome structures,\nlike API documentation,\nmay come with an outline template to follow.\nBut many others,\nlike the inverted pyramid,\ndo not.\n\nThis phase is all about taking your chosen structures\nand combining them with the details of your subject\nto produce the skeleton of your document.\n\nThe outline itself is a simple hierarchical list of\nthe things you want to communicate\nand the approach you want to take at each step.\nParticularly for smaller projects,\nthe line between choosing a structure and outlining can be rather blurry.\n(Evidenced by the the section on choosing structures ending with an outline!)\nBut an outline should show in detail **how** you intend to implement your chosen structure.\n\n### How detailed should an outline be?\n\nThis will likely vary from person to person,\nbut I prefer to outline in enough detail that\neach low level bullet point corresponds to one or two paragraphs in the final text.\nThis gives me sufficient guidance that I don't get lost,\nbut also gives me enough flexibility to expand on some points without deviating from the outline.\n\n### How do you actually create the outline?\n\nThere are two basic approaches:\ndepth-first\nand breadth-first.\nA depth-first approach starts at the top\nand explores all the way down to the details one point at a time.\nA breadth-first approach starts at the highest level\nand only becomes more detailed after all the higher level points have been filled in.\n\n**Partially completed depth-first outline**\n\n* Point 1\n    * Point 1.1\n        * Point 1.1.1\n        * Point 1.1.2\n        * Point 1.1.3\n\n**Partially completed breadth-first outline**\n\n* Point 1\n* Point 2\n* Point 3\n* Point 4\n* Point 5\n\nBreadth-first generally produces better results,\nbecause it provides more overall context each time we step down a level of detail.\nThat extra context makes it much less likely that we will get stuck on trivia.\n\n### Evaluate and revise\n\nOnce you've drafted your outline,\nbe sure to evaluate it with your goals and audience in mind.\nIt is much easier to move or edit a few bullet points\nthan to revise entire sections of your document.\n\n## 5. Turn the outline into prose\n\nEverything we've talked about so far has been aimed at preparing you for this part of the process.\nYou should know your goal, audience and structure.\nAnd your outline gives you a game plan.\nNow it's time to turn all that into something for others to read.\n\n### Putting flesh on the bones\n\nRight now what you've got is a skeleton.\nIt's vaguely in the shape you want,\nbut if it tried to walk around it would quickly fall apart.\nThere are two principle things that it is lacking:\nmuscle to give it strength,\nand ligaments to hold things together.\nLet's start with the muscle.\n\nBare statements of fact rarely carry much weight with readers,\nregardless of how important those facts might be.\nThey have to be elaborated on\nand placed into their proper context.\nAnd usually the most important context for a reader is the answer to \n\"Why do I care about this?\"\nA reason to care gives your prose strength.\n\nConsider this example:\n\n> Continuous integration improves the development process.\n\n> Continuous integration improves the development process by helping us detect defects sooner.\n> That means fewer late night calls to debug production.\n\nThe latter includes more supporting detail about _how_ it helps,\nas well as a reason for developers to care about it.\n\nIn addition to muscle we need ligaments.\nThe ligaments are what actually connects one bone to another.\nThe prose equivalent is a transition.\n\nSudden jumps from one topic to another\n(even closely related)\nare jarring.\nTransitions serve to smooth that over by\nclearly signaling the close of one topic,\nthe introduction of the next,\nand possibly how they are related.\n\nA transition can be a simple phrase.\nIt can be an entire sentence.\nIt can be a paragraph.\nOr multiple paragraphs.\nIt all depends on the size of the pieces you're transitioning between.\n\nFor an example, take a look at the paragraph that started this section (#5) above.\n\n### It's not necessarily exposition\n\nWhen working from your outline,\nbeware of always choosing the most direct expansion of your points.\nSimple exposition is the most common way of describing things,\nbut it isn't always the best.\nUsing other forms of expansion will give your prose variety and help maintain reader interest.\n\nEspecially in a longer text,\nincluding the occasional story, joke, or anecdote\ncan make the difference between a pleasant read or an unbearably boring one.\n\nWhatever you choose to use,\nit should be integrally related to the points you're trying to make.\n\nThere is a story about a high school student who had to give a book report.\nWhen he stood up in front of the class he yelled,\n\"Sex! Sex! Sex!\"\nthen continued,\n\"Now that I have your attention,\nI'd like to talk to you about The Complete History of World War II.\"\n\nDon't be like the high school student.\n\n## 6. Revise\n\nAt this point you have a fleshed out draft,\nso now it is time to fix the gaps and rough edges.\n\n### Evaluate\n\nStarting at the beginnning, read each unit of your work.\nDepending on the length of your document, that unit might be a paragraph, section, or chapter.\nAs you read, ask yourself the following questions:\n\n* Does this advance the goal?\n* Is it clear?\n* Is it concise?\n* Is it well organized?\n* Is it scannable?\n\nYou'll likely want to read the unit multiple times to answer these questions.\nFor a longer unit, one read per question -- or even more -- may be appropriate.\n\n> #### Tip: Try different contexts\n>\n> Reading in a different context than you usually write in can help you to see things differently and spot problems more easily.\n> For example, if you usually write at a computer,\n> try printing your document out on paper,\n> or even reading it out loud.\n\n### Plan your corrections\n\nTake notes on each thing that needs to be improved,\nbut don't make corrections right away.\nIntroducing a slight delay between identifying the problem and attempting to fix it\nwill give your mind a chance to work on the problem,\nand often arrive at a better solution than the first one you thought of.\n\nYour notes can take many forms:\na separate text file,\nusing Track Changes in Microsoft Word,\nand so on.\nI tend to prefer annnotating a physical paper with pen or pencil,\nbut you should experiement and find what works best for you.\n\nAfter you have a list of all the corrections you plan to make,\nyou may be able to spot common patterns for future improvement.\nBut the immediate task is to begin making corrections.\n\n### Make your corrections\n\nProceed through your notes from beginning to end,\ncorrecting each problem.\nIf you get stuck on something,\nleave it to the side for now.\nYou'll come back to it later.\n\nOnce you've completed all the corrections you were able to make,\ntake another look at any you left behind.\nYou may know how to fix them now.\nIf so, go ahead.\nIf not, we'll leave them for the next stage of the writing process: feedback.\n\n## 7. Get feedback\n\nUp to this point everything has come from you,\neven thinking about the audience.\nBut this is where you actually engage with other people for the first time.\nBrace yourself,\nbecause feedback from real people is almost certain to suprise you,\nregardless of whether it's positive or negative.\n\n### Sources of feedback\n\nGenerally you will be getting feedback from one of three types of readers:\nmembers of the target aurdience,\nexperts on the subject,\nand friends/coworkers.\nEach of these groups has strengths and weaknesses.\nGetting feedback from all three is ideal,\nand occasionally the groups overlap,\nbut feedback from any of them is useful for checking your assumptions.\n\n#### Target audience\n\nMembers of the target audience are extremely valuable\nbecause they can tell you whether your writing is achieving the intended goal.\nUnfortunately, they often can't tell you why.\nAnd even if they do offer a reason,\nit shouldn't always be taken at face value.\n\nTo help overcome this issue,\nit can help to supply a list of specific questions for them to answer.\nFor example:\n\n* By the end did you think that it is worth investigating the new technology I described?\n* If not, was there a specific point where I lost you?\n* Did any of my supporting evidence seem questionable?\n\nUnfortunately, it can be difficult or impossible to get feedback from the audience.\nAfter all, when drafting an email to your boss's boss,\nyou can't very well ask them to proofread it.\n\n#### Experts\n\nExpert feedback can also be very useful,\nparticularly for identifying inaccuracies and mistakes.\nOne issue to watch out for, though,\nis that experts may not remember what it was like to be a beginner.\nSo if beginners and non-experts are in your target audience,\nbe careful of suggestions to includes lots of additional details which they won't have the context to understand.\n\n#### Friends and coworkers\n\nFriends and coworkers are often the easiest reviewers to obtain.\nUnfortunately, they are often the least reliable in providing needed correction.\nNo one wants to hurt the feelings of someone they like.\nBut they are often excellent at providing encouragement,\nand when working on a large writing project,\nthat can be invaluable.\n\n### Evaluating feedback\n\nWhen evaluating the feedback there are a few principles to keep in mind.\n\nFirst, _readers are always right about their reactions_.\nIf a reader says that they were confused by a certain point,\nthen they were,\nno matter how clear it may appear to you.\n\nSecond, _a reader's negative reaction does not automatically lead to revision_.\nIt is your responsibility to evaluate\nwhether issues raised are actually problems for your target audience\nand serious enough to require addressing.\n\nThird, _a reader's proposed solution may not be correct_.\nSometimes readers will suggest solutions without explaining the problem they identified.\nFor example, \"I think you need a fancy graphic right here.\"\nThis suggestion might be a good one,\nbut you should work to understand the underlying problem.\nPerhaps the text became boring,\nor perhaps a diagram would help with clarity.\nWhatever the case may be,\ndon't just take the suggestion at face value.\n\nFinally, _a reader's feedback should be weighted differently based on who they are and what area their feedback is in._\nAn expert's feedback regarding correctness should be prioritized over a beginner's,\nand an audience member's feedback regarding readability should be prioritized over the expert's.\n\n### Compile the feedback into revision notes\n\nAfter taking all of this in,\nyou should have a list of changes to make.\nAnd you may also have a list of positive points which you should try to retain.\nDespite the focus on improving problems,\nyou also don't want to edit away something that is working.\n\n## 8. Revise based on feedback\n\nJust like with your first revision notes,\nyou will go back through and make your changes one at a time,\nevaluating the criteria of clarity, concision, organization, scannability and goal focus.\nBy the time you are done,\nyou should have a pretty solid draft.\n\nAs you revise, make changes one at a time,\nassessing clarity, concision, organization, scannability, and goal focus.\nPay attention to common themes in the feedback you receive.\nThose are the ones most likely to require revision.\n\nRemember to prioritize the most significant changes first.\nTackle issues like organization or persuasiveness before minor details like grammar.\nGetting something grammatically correct is a waste of time\nif that entire section will be reworked or removed.\nThroughout revision, continuously review your goals and audience,\nand be prepared for multiple rounds of changes.\n\nAfter you've revised, seek additional feedback,\nboth to verify initial concerns are addressed\nand to ensure no new problems have been introduced.\nConsult with both original and new readers to get different perspectives.\nRemember, continuous revision is crucial for producing a polished and effective piece of writing.\n\n## 9. Publish\n\nPublishing your work is usually the most critical part of the writing process,\nbut remember, it can happen at any point, depending on the project.\nIn some cases, publishing might be part of an ongoing process,\nwith updates and revisions made after the first release.\nThis is especially true for things like wiki-based technical documentation\nor presentations that are given multiple times and need tweaks based on audience feedback.\n\nBefore you publish, think about the context and the level of polish your writing needs.\nNot every situation calls for super polished writing.\nA quick email to a coworker won't need the same level of refinement as a formal report for the big boss.\nAdapt the level of polish to the context so you strike the right balance between quality and getting things done.\n\nBefore hitting that publish button,\ngive your work a once-over for any errors or inconsistencies,\nand make sure your formatting looks good,\nbased on what's required in your situation.\nThis final check is crucial for presenting your writing in the best light.\n\nAfter publishing, don't forget to spread the word.\nShare your work with the people who need to see it,\nwhether that's passing a report to colleagues,\nposting a blog on social media,\nor presenting your findings at a conference.\nKeep in mind that publishing doesn't mean you're done with revisions.\nBe open to feedback even after your work is out there,\nand be ready to make updates or corrections as needed.\nEmbracing this back-and-forth will help you keep improving your writing skills\nand adapt to the needs of your audience in all kinds of situations.\n\n## Summing it up\n\nThe writing process is all about striking the right balance between the formal process and the needs of the situation.\n\nFrom setting goals and figuring out who you're writing for,\nto making an outline,\nrevising,\nand hitting that publish button,\neach step is important.\nBut not equally important.\n\nKeep an eye on your context and switch things up as needed,\nwhether it's the level of polish or the amount of feedback and revision you're going for.\nDon't forget, the process can and should be trimmed down when it makes sense for the situation,\nhelping you focus on what's most important in each specific context.\nThe more you work at it, the better you'll get at writing and connecting with your audience.\n\nWriting takes time, practice, and being open to learning from both the things you nail and the things you, well, don't.\nAs you gain experience as a writer,\nyou'll find that this whole process starts to feel more natural,\nand your ability to get your point across will only get better.\nJust keep writing, learning, and tweaking your process to fit each unique writing situation you find yourself in."
  },
  {
    "path": "manuscript/rules.json",
    "content": "{\n  \"title\": \"General Rules\",\n  \"eleventyNavigation\": {\n    \"key\": \"General Rules\",\n    \"order\": 2\n  }\n}"
  },
  {
    "path": "manuscript/rules.md",
    "content": "# General Rules\n\nRules.\nThe very word can trigger skepticism.\nAnd understandably so.\nWe are often confronted with seemingly arbitrary rules\nwhich make our lives harder for no apparent reason.\n\nIn this chapter I will give you rules to follow,\nbut I will also explain each rule's rationale.\nSo if you find yourself in a situation beyond the scope of the rule,\nyou'll be equipped to make intelligent decisions about how or if to apply it.\n\nIt is also important to acknowledge the limits of these rules.\nThey are targeted principally at writing within a professional business context.\nIf you are writing a novel,\nthese rules will be of limited use.\nAnd if you are writing poetry,\nthey will probably be entirely useless.\nBut if you need to communicate ideas to your coworkers,\nthen these rules will serve you well.\n\nNow that we've set the appropriate context, let's look at those rules.\n\n## 1. Be goal oriented.\n\n> \"In my end is my beginning.\"\n> \n> -- T.S. Eliot\n\n### Everything you write has a goal\n\nSuppose a boss or client came to you and said they needed you to build a web application.\nYour first question would probably be,\n\"What is the application for?\"\nThe very idea of writing an application without knowing its purpose is ridiculous.\nYet when it comes to writing prose,\nwe too often fail to ask the obvious question.\n\nEverything you write has a goal,\nwhether explicit or implicit.\nThose API docs?\nThe stated goal is to inform other developers how to use your library.\nThat weekly status report you email your client?\nThe unstated goal is reassuring them that their money is being well spent.\n\nThe goal of a document isn't always obvious,\nbut in the next chapter, we'll look at some tools to figure it out.\n\n### Knowing the goal equips you to fulfill it.\n\nLet's go back to our hypothetical web application above.\nSuppose you did try to build it without actually knowing its purpose?\nYou are just given a list of features and told to start building.\nWhat would happen?\n\nYou'd have no way to evaluate how well or poorly the application was doing.\nAnd that's not just a problem at the end.\nAll along you'd have questions about how best to build each feature.\nBut without knowing the application's purpose,\nyou'd have no way of choosing between the alternatives.\nThat kind of uncertainty is crippling.\nAnd I suspect that is why many people avoid writing.\n\nBut when you do know the goal you are writing toward,\ndecisions are easier,\nand it is simpler to tell whether your writing succeeds in achieving its end.\n\n### The structure of goals\n\nWe've talked about goals a lot,\nbut so far we haven't really clarified what kind of goals we're talking about.\nIt's all about the document.\n\nIn this book,\nwhen I talk about goals,\nI mean the purpose intrinsic to the document[^telos],\nnot the author's personal motivations.\nFor instance,\nyour goal in writing API docs may be to keep your tech lead from bugging you about it yet again.\nBut the purpose of the docs themselves is to assist users of the API.\n\nA document's goals will generally fall into one of two categories:\nto inform or to persuade.\nMost documents will include a bit of both,\nbut one will be primary.\nTo go back to the API docs example,\nit may help persuade people to use your library,\nbut the primary purpose is just to inform them about how to do so.\n\n[^telos]: If you're familiar with ancient Greek philosophy,\nthis is what Aristotle would call the document's _telos_.\n\n## 2. Be concise.\n\nIn a professional context,\neveryone is pressed for time.\nBeing concise is about respecting your readers' time.\nDon't force them to read a page when a paragraph will do.\n\nConciseness also helps you achieve your goal.\nThe more time investment your text requires,\nthe more reluctant readers will be to give it to you.\nSo we should do our best to keep the required investment to a minimum.\n\nAt the same time, conciseness does not mean being excessively terse.\nConciseness means saying the exact amount necessary to achieve the goal:\nno more and no less.\n\n## 3. Be Clear\n\n### Avoid ambiguity\n\nHuman language is rife with ambiguity.\nTake as an example my first title idea for this book:\n\"Writing for Developers.\"\nOnly three words,\nyet it could be read in two totally different ways.\nThat title could have meant\n-- as I intended --\n\"A book for developers on the subject of writing.\"\nBut another equally reasonable interpretation was,\n\"A book on writing for an audience of developers.\"\n\nAmbiguous language is useful in art and poetry,\nbut not when we are trying to communicate as efficiently as possible.\n\n### Avoid jargon\n\nIt is also wise to avoid unfamiliar terms and jargon.\nOf course, this is dependent on your audience.\nTo a developer, this sentence makes perfect sense:\n\n> \"Hoth is a lightweight MVVM framework\n> which leverages dirty checking\n> and immutable data structures for performance.\"\n\nTo a non-developer,\nit sounds more like this:\n\n> Hoth is a lightweight magic framework\n> which leverages scary magic\n> and scarier magic for performance.\n\nFor readers unfamiliar with the terminology it communicates next to nothing.\n\n### Narrow the scope of your words\n\nWe love to speak in generalities.\nPerhaps because it is difficult to definitely prove a generality wrong.\nThe problem is that the more general a statement is,\nthe more difficult it is to understand and apply.\nConsider this example:\n\n> Object-oriented programming is terrible.\n\nIt's not completely meaningless,\nbut it is extremely broad,\nand the implications are unclear.\nShould readers avoid all object oriented languages?\nIt's hard to tell what the author is thinking.\n\nContrast with this:\n\n> Class-based inheritance tends to make code unnecessarily complex.\n\nThis version has narrowed the scope in two ways.\nIt has narrowed from all object-oriented programming to class-based inheritance.\nAnd it has narrowed from \"terrible\" to \"tends toward unnecessary complexity.\"\nAs a result,\nthis sentence is much easier to understand and evaluate.\n\nGiven the choice between the specific and the general, choose the specific.\n\n## 4. Be organized.\n\nFor many people this is the most difficult part.\nThey know the goal.\nThey can write clear, concise sentences.\nBut they have a hard time putting those pieces together into a coherent whole.\n\nIn the next chapter we'll look at how to do it.\nFor now let's explore why.\n\n### Structure aids comprehension\n\nThe human mind is built for pattern matching.\nAnd it is pretty good at its job,\notherwise we'd have all been eaten by tigers long ago.\n\nConsider two different lists:\n\n* Apple pie\n* Blueberry pie\n* Cranberry pie\n\n* Wrench\n* Justice\n* Puppy\n\nThe first list is much more memorable and comprehensible.\nWhy?\nBecause it is organized into a structure that our minds can easily extract.\nEach item in the list was a pie.\nEach of the pies was fruit-based.\nAnd the pies were alphabetically ordered.\nBut the second list had no unifying organizational structure.\n\n### Structure is fractal\n\nWriting structures are simultaneously high level and low level.\nThey encompass everything\nfrom your three main points\nto that sub-sub-sub-point in paragraph 45.\nAnd if you've chosen your structure well,\nthe micro and macro levels will tend to mirror each other.\nFor example, consider this outline for an article on the Hoth Framework.\n\n> * Intro to Hoth\n> * Immutable data structures\n>   * Intro\n>   * Benefits\n>   * Examples\n> * Dirty checking\n>   * Intro\n>   * Benefits\n>   * Examples\n> * Example application\n> * Conclusion\n\nBoth of the main sub-points follow the same structure as the outline as a whole.\nThe mirroring isn't always this obvious,\nbut it is generally present.\n\n### Projects may come with built-in structure\n\nCertain kinds of projects come with ready-made,\nvery detailed structures,\nsimply because of how common that type of project is.\nAPI docs,\nfor example,\nmay vary a bit by language,\nbut will generally look pretty close to this.\n\n* Modules\n  * Name\n  * Description\n  * Classes\n    * Name\n    * Description\n    * Methods\n      * Name\n      * Arguments\n      * Return value\n      * Description\n\nNot every predetermined structure is that specific, though.\nLibrary websites have several things they need to include,\nlike language,\npurpose of the library,\nand how to install it,\nbut they also have more flexibility.\n\n### General purpose structures\n\nIn addition to these very specific structures,\nthere are also many general purpose structures.\nThese are things like the inverted pyramid, objection-response, etc.\n\nTypically you will pick two or three of these general purpose structures\nand use them as the organizing principle of the project.\n\n## 5. Be scannable.\n\nWhile the previous rule was about the conceptual structure of a text,\nthis rule is about the visual typographic structure.\nThe point of scannability is to allow readers to locate important information at a glance,\nrather than reading every word on the page.\nEven for readers that do read every word,\nscannable typography makes it easier to refer back to key ideas in the text.\n\n### Break text into bite-sized pieces\n\nHave you ever read a paragraph that took up an entire printed page?\nThey are no fun to read.\nWith no visual breaks,\nit is difficult to keep track of where you are,\nmuch less follow the flow of ideas.\n\nTo maximize scannability,\ntext should be broken into bite-sized units of thought.\nParagraphs, for example, should generally be 2-5 sentences long.\nMuch longer and it becomes difficult to read.\nShorter and you may want to use a heading instead.\n\n### Divide and conquer with headings\n\nThe primary purpose of headings is to make your text's conceptual structure explicit.\nHowever, they also have two important scannability implications.\n\nFirst, headings provide a visual anchor allowing readers to locate where a concept is discussed.\n\nSecond, headings breaks the text into units of progress which help the reader stay motivated to continue.\nThis is part of the reason list posts are such a popular article format.\nEach time the reader reaches the next heading,\nthey get to cross something off their mental checklist.\n\n### Use lists for your lists\n\nWhile not as common as paragraphs,\nthe humble list is one of the author's most helpful tools.\nIt provides:\n\n* Visual attraction for the list\n* Visual attraction for each item in the list\n* A break from the monotony of paragraphs\n* A sense of progress\n\nYou can, of course, embed lists directly into your sentences and paragraphs.\n\n> While not as common as paragraphs,\n> the humble list is one of the author's most helpful tools.\n> It provides:\n> visual attraction for the list,\n> visual attraction for each item in the list,\n> a break from the monotony of paragraphs,\n> and a sense of progress.\n\nHowever, doing so relegates the list contents to a secondary status.\nIn general,\nusing typographic lists\n(bulleted, numbered, etc.)\nfor your conceptual lists makes sense if the exact contents are worth emphasizing.\n\n### Emphasize key ideas with bold or italics\n\nOrdinary paragraphs are the parts of a text most likely to be skipped over.\nBut sometimes important ideas only make sense as part of a paragraph.\nThat's where typographic emphasis comes in.\n\nHighlighting important ideas with bold or italics allows readers to see key ideas at a glance.\n\nHowever, there are some rules of thumb to keep in mind.\n\n* Only highlight one phrase or sentence per paragraph.\n* Don't highlight something in _every_ paragraph.\n* **Never** highlight something with both bold and italics.\n\nGo beyond these limits and readers are likely to feel that you are shouting at them."
  },
  {
    "path": "manuscript/why.json",
    "content": "{\n  \"title\": \"Why should developers study writing?\",\n  \"eleventyNavigation\": {\n    \"key\": \"Why should developers study writing?\",\n    \"order\": 1\n  }\n}"
  },
  {
    "path": "manuscript/why.md",
    "content": "# Why should developers study writing?\n\nIf you've picked up this book, then you're probably a software developer.\nFurthermore, you're someone who cares about your career.\nYou've probably spent countless hours\nstudying manuals,\nreading library docs,\nlearning how to write clean code,\nand otherwise mastering your craft.\n\nBut you may be skeptical.\nThere are a thousand other things you could learn.\nWhy spend the time studying writing?\nLet's walk through some of the things you might be thinking.\n\n## I'm paid to code, not to write.\n\nIn most cases, developers aren't paid to code.\nWe are paid to produce working software that solves a business problem.\nIn order to do that we may need to:\n\n* Email a product manager to clarify a requirement\n* Instant message a designer to verify the color and placement of a call-to-action button\n* Document the details of an internal REST API\n* Submit a patch to an open-source project you use\n* File a bug report about a part of the software developed by another team\n* Provide explanatory notes about that spike in server errors on the 14th\n* Tweak the wording of some UI text that is confusing users,\n  since the designer is unavailable\n\nAll of these things are run of the mill tasks for a software developer.\nAnd every single one of them is a form of writing.\n\n## I already know how to write. I did well in school.\n\nUnfortunately, literacy,\neven at college or university level,\ndoesn't guarantee the ability to write effectively.\nMany degree programs place little emphasis on writing.\nAnd those that do emphasize it often encourage an academic style which doesn't mesh well with most developer's jobs.\n\nAcademic writing tends to value a kind of distant objectivity which can manifest as:\n\n* Unnecessary jargon\n* Verbose and indirect prose\n* Extreme formality\n\nIn contrast, most developers would benefit from making their prose clear, direct, and concise.\n\n## But I could be studying the Hoth framework instead. It's so cool!\n\nYes, no matter which topic you decide to study,\nyou will be passing up something else.\nBut writing deserves special consideration.\nWhy?\n**Because writing is a durable skill.**\n\nTechnology changes quickly.\nIf you're not careful,\nyou can easily invest a lot of time and energy into a technological one hit wonder.\nWriting, though, will never be rendered obsolete by the fickle winds of technology or fashion.\n\n**Writing is also a transferable skill.**\nIf you decide to change careers and become a\nrealtor,\nlandscape artist,\nor -- God forbid! -- a manager,\nyour expertise in the Hoth MVVM framework will be of limited use.\nBut writing will remain.\n\n## But what will I get out of studying writing?\n\n### Less back and forth\n\nWe've all experienced out of control email threads.\nIt starts with a vague question,\nis usually followed by an ambiguous answer,\nand before you know it,\nsomeone in another department is freaking out about a non-existent problem.\n\nWhat if you could step in and make people understand?\nEven better, what if you could prevent the issue from escalating in the first place?\nThat's the power of clear and effective writing.\n\n### Fewer bugs and less rework\n\nSometimes we run across frustratingly mysterious bits of code.\nPerhaps we've even written some ourselves.\nBut what's even more frustrating\nis when the code is accompanied by an equally mysterious comment like,\n\"fixes IE bug.\"\n\nWhat IE bug? And which version of IE?\n\nA developer working on this code, now needs to:\n\n* Talk to the original programmer,\n  who won't remember anything.\n* Manually test to see if there are obvious bugs related to that line,\n  which he probably won't catch.\n* And perhaps make changes anyway,\n  without knowing what he broke.\n\nA clearly written comment would have prevented all of that.\n\n### Protect your development flow\n\nTalking face to face is a valuable and necessary part of our jobs.\nBut not every face to face conversation is valuable.\n\nIf you find yourself explaining certain things over and over again\n(perhaps because you're an expert in a particular subsystem)\nthen you should write it down in a public location like a team wiki.\nIf your explanations are clear and easy to understand,\nyou'll have fewer interruptions messing with your development flow.\n\n### Recognition of your expertise\n\nPerhaps you have a different problem.\nYou have a deep knowledge of some tool, library, or system,\nbut no one realizes it.\nWriting guides, tutorials, and presentations\ncan help you achieve greater recognition,\nboth inside and outside your company.\n\n### Greater trust from managers\n\nWatching a software development project from the outside can be a frustrating experience.\nThis is doubly true if you are on the hook when something goes wrong.\n\nA developer who can clearly articulate the state of the project,\nwithout getting bogged down in technical details,\nis invaluable.\n\nIf you are that developer,\nyou will quickly earn the trust of your manager and non-technical colleagues.\n\n### Improve your own understanding\n\n> \"How can I tell you what I think till I see what I say?\"\n> \n> -- E.M. Forster, _Aspects of the Novel_\n\nThe process of writing takes our often fuzzy and unformed ideas,\nand shapes them into something clear enough to communicate to others.\nThis makes writing an excellent way to deepen our own understanding of a subject.\nSometimes the improvement comes from research,\nbut often it comes simply due to organizing our own thoughts.\n\n## What now?\n\nHopefully by this point you can see why studying writing is worthwhile.\nIn the next chapter,\nwe'll launch into some general rules you can use to improve your writing."
  },
  {
    "path": "netlify.toml",
    "content": "[build]\n  publish = \"_site\"\n  command = \"npm run build\"\n  #command = \"npm run build && set -e && find ./_site -type f -name '*.html' -exec staticrypt -f password_template.html {} $PASSWORD -o {} \\\\;\"\n  functions = \"functions\"\n\n# REDIRECT and HEADERS examples\n\n# Redirect rule example\n# For more information see:- https://www.netlify.com/docs/netlify-toml-reference/\n\n#[[redirects]]\n#  from = \"/*\"\n#  to = \"/blog/:splat\"\n\n# The default HTTP status code is 301, but you can define a different one e.g.\n# status = 302\n\n# Headers rule example\n# For more information see:- https://www.netlify.com/docs/netlify-toml-reference/\n\n#[[headers]]\n#   Define which paths this specific [[headers]] block will cover.\n#   for = \"/*\"\n\n#[headers.values]\n#   X-Frame-Options = \"DENY\"\n#   X-XSS-Protection = \"1; mode=block\"\n#   Content-Security-Policy = \"frame-ancestors https://www.facebook.com\"\n\n# Redirects and headers are GLOBAL for all builds – they do not get scoped to\n# contexts no matter where you define them in the file.\n# For context-specific rules, use _headers or _redirects files, which are\n# applied on a PER-DEPLOY basis.\n"
  },
  {
    "path": "outline.md",
    "content": "# Prose for Programmers Outline\n\nChecked boxes indicate that the initial draft of a section is complete.\n\n## [Why should developers learn to write?](manuscript/why.md)\n\n- [x] Objections\n    - [x] Paid to code, not write\n        - [x] Laundry list of writing developers have to do\n        - [x] Coding is writing\n    - [x] I already know how to write. I did well in school.\n        - [x] Literacy, even college level, doesn’t mean your writing is good\n        - [x] Academics can even foster bad writing habits\n    - [x] But I could be learning technology X instead\n        - [x] Writing is a durable skill\n        - [x] Writing is a transferable skill\n- [x] Benefits\n    - [x] fewer back and forth emails/chats\n    - [x] Fewer bugs due to misunderstood code/docs\n    - [x] Fewer interruptions from coworkers with questions (keep flow)\n    - [x] More understanding/empathy from managers\n    - [x] Recognition of your knowledge\n    - [x] Increase your own understanding\n\n## [General Rules](manuscript/rules.md)\n\n- [x] Be goal oriented\n    - [x] Everything you write has a goal or purpose\n        - [x] may be implicit or explicit\n    - [x] Understanding the goal promotes better writing\n    - [x] Structure of goals\n        - [x] 2 types\n            - [x] inform\n            - [x] persuade\n        - [x] Most writing serves both to one degree or other\n        - [x] But most writing has a primary goal, with others as secondary\n- [x] Be concise\n    - [x] Not short or terse\n    - [x] Everything contributes to the goal\n    - [x] Avoids wordiness for the sake of the goal\n- [x] Be clear\n    - [x] Avoid unfamiliar or unnecessary jargon\n    - [x] Avoid ambiguity\n    - [x] Be precise\n- [x] Be organized\n    - [x] Human mind uses patterns to extract meaning\n    - [x] Structure is fractal: macro and micro mirror each other\n    - [x] Projects may come with built-in structure (API docs)\n    - [x] Several general purpose structures available\n- [x] Be scannable\n    - [x] Typographic structure to direct attention to ideas\n    - [x] Break up text into digestible chunks\n    - [x] use headlines\n    - [x] use lists\n    - [x] Make use of bold and italic to highlight points\n\n## [The Writing Process](manuscript/process.md)\n\n- [x] Determine the goal\n    - [x] Why am I writing this?\n        - [x] Purpose of doc\n        - [x] Not personal motivations\n    - [x] Keep asking why\n- [x] Determine audience\n    - [x] Who will be reading this?\n    - [x] Given the goals, which readers are the primary audience?\n    - [x] What is their relation to the subject?\n    - [x] What is their relation to you?\n    - [x] Examples of how audience affects writing\n- [x] Choose a suitable structure\n    - [x] Different structures are suitable for different goals\n        - [x] Hierarchical structures are often good for informational\n        - [x] Narrative is good for persuasive\n    - [x] Different structures for different audiences\n        - [x] Expertise in topic\n            - [x] Shallow bullet points\n            - [x] Deep information hierarchy\n        - [x] Level of interest\n        - [x] Relationship\n    - [x] Can mix and match\n        - [x] Examples\n- [x] Build an outline\n    - [x] Structure may come with an outline template (API docs)\n    - [x] List of the ideas you want to communicate\n    - [x] Evaluate outline based on goal and audience\n    - [x] Revise outline\n        - [x] Revising earlier is cheaper\n- [x] Turn outline into prose\n    - [x] Put flesh on the bones\n        - [x] Muscles: human connection/emotion for strength\n        - [x] Connective tissue: transitions between ideas\n    - [x] Not necessarily exposition\n        - [x] Stories\n        - [x] Jokes\n- [x] Revise\n    - [x] Evaluate\n        - [x] Does this unit advance the goal?\n        - [x] Is it concise?\n        - [x] Is it clear?\n        - [x] Is it organized?\n        - [x] Is it scannable?\n    - [x] Plan a correction\n    - [x] Make corrections\n- [x] Get feedback\n    - [x] Types of readers\n        - [x] Target audience\n        - [x] Experts\n        - [x] Friends\n    - [x] Evaluating feedback\n        - [x] Readers are always right about their reactions\n        - [x] Readers may be wrong about the problems and solutions they identify\n        - [x] Bear in mind what kind of reader this is\n    - [x] Produce a list of problems to address and good points to keep\n- [x] Revise based on feedback\n    - [x] See previous\n- [x] Publish\n    - [x] May be done at any point (depending on project)\n    - [x] Can be part of an iterative process\n    - [x] Tell people about it\n    - [x] Not the end of revision\n- [x] Conclusion\n    - [x] Abbreviate process as appropriate\n\n## Writing Structures\n\n- [ ] General Structures\n    - [ ] Inverted Pyramid\n        - [ ] what it is\n        - [ ] why it is useful (time saving)\n        - [ ] high level\n        - [ ] low level (topic sentences)\n    - [ ] List\n    - [ ] Sequence\n    - [ ] Q & A ?\n- [ ] Informational Structures\n    - [ ] Hierarchy\n        - [ ] Examples\n            - [ ] Textbooks\n            - [ ] API Docs\n- [ ] Persuasive structures\n    - [ ] Objection - response\n    - [ ] Persuasive version of Q&A\n    - [ ] Problem - solution\n    - [ ] Story\n    - [ ] Syllogism\n    - [ ] Juxtaposition (attention grabbers)\n- [ ] Combine as appropriate\n    - [ ] Examples\n\n## Audience\n\n- [ ] Aspects of audience\n    - [ ] Expertise in subject\n    - [ ] Relationship to you\n    - [ ] Motivation for reading\n    - [ ] Emotional state\n    - [ ] Level of caution/skepticism\n- [ ] Common audiences for developers\n    - [ ] Other developers\n        - [ ] Somewhat similar outlook on the world\n        - [ ] Not necessarily the same as you\n            - [ ] Experience\n            - [ ] Different technologies\n            - [ ] Corporate vs startup\n    - [ ] QA & testers\n    - [ ] Designers\n    - [ ] Teammates\n    - [ ] Non-technical peers\n    - [ ] Your boss\n    - [ ] Management\n    - [ ] Ops/SysAdmin\n    - [ ] Users\n    - [ ] Clients\n    - [ ] Customers\n\n## Genres\n\n- [ ] Genres\n- [ ] Email\n- [ ] Docs\n- [ ] Code Comments\n- [ ] Blog posts\n- [ ] Chat?\n- [ ] Project site\n- [ ] Case for new technology\n- [ ] Requirements\n- [ ] Bug reports\n- [ ] Error messages\n- [ ] Help articles\n- [ ] UI text\n- [ ] Commit messages\n- [ ] Code review\n- [ ] Code?\n- [ ] Talks/presentations?\n\n## Other Resources\n\n- [ ] Books\n    - [ ] The Elements of Style by Strunk & White\n    - [ ] The Economist Style Guide\n    - [ ] Steering the Craft by Ursula K. Le Guin\n    - [ ] On Writing Well by William Zinsser\n    - [ ] Writing That Works by Ogilvy?\n    - [ ] Team Geek?\n- [ ] Applications & Tools\n    - [ ] Workflowy\n    - [ ] Writeroom\n    - [ ] Writemonkey\n    - [ ] IA Writer\n    - [ ] Hemingway?\n    - [ ] write-good npm library?"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"spacebook\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple site generator based on Eleventy, Tailwind 2.0, and Alpine.js\",\n  \"scripts\": {\n    \"start\": \"eleventy --serve & postcss styles/tailwind.css --o _tmp/style.css --watch\",\n    \"build\": \"ELEVENTY_PRODUCTION=true eleventy && NODE_ENV=production postcss styles/tailwind.css --o _site/style.css &&  ./node_modules/.bin/cleancss -o _site/style.css _site/style.css\",\n    \"watch\": \"npx eleventy --watch\",\n    \"debug\": \"DEBUG=* npx eleventy\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/broeker/spacebook.git\"\n  },\n  \"author\": \"Tim Broeker <broeker@gmail.com> (https://www.electriccitizen.com/)\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/broeker/spacebook/issues\"\n  },\n  \"homepage\": \"https://github.com/broeker/spacebook\",\n  \"devDependencies\": {\n    \"@11ty/eleventy\": \"^0.11.1\",\n    \"alpinejs\": \"^2.7.3\",\n    \"eleventy-plugin-lazyimages\": \"^2.1.0\",\n    \"eslint\": \"^7.9.0\",\n    \"lazysizes\": \"^5.2.2\",\n    \"luxon\": \"^1.25.0\",\n    \"markdown-it\": \"^10.0.0\",\n    \"markdown-it-anchor\": \"^5.3.0\",\n    \"markdown-it-image-lazysizes\": \"^1.0.0\",\n    \"postcss-cli\": \"^8.3.0\",\n    \"prettier\": \"^2.1.2\",\n    \"tailwindcss\": \"^2.0.2\"\n  },\n  \"dependencies\": {\n    \"@11ty/eleventy-img\": \"^0.5.0\",\n    \"@11ty/eleventy-navigation\": \"^0.1.6\",\n    \"@tailwindcss/forms\": \"^0.2.1\",\n    \"@tailwindcss/typography\": \"^0.3.1\",\n    \"autoprefixer\": \"^10.1.0\",\n    \"clean-css\": \"^4.2.1\",\n    \"clean-css-cli\": \"^4.3.0\",\n    \"elasticlunr\": \"^0.9.5\",\n    \"eleventy-plugin-embed-everything\": \"^1.9.4\",\n    \"eleventy-plugin-nesting-toc\": \"^1.2.0\",\n    \"eleventy-plugin-svg-contents\": \"^0.7.0\",\n    \"eleventy-plugin-toc\": \"^1.1.0\",\n    \"emoji-regex\": \"^9.2.0\",\n    \"html-minifier\": \"^4.0.0\",\n    \"markdown-it-attrs\": \"^3.0.3\",\n    \"markdown-it-center-text\": \"^1.0.4\",\n    \"markdown-it-container\": \"^3.0.0\",\n    \"markdown-it-emoji\": \"^2.0.0\",\n    \"markdown-it-footnote\": \"^3.0.2\",\n    \"markdown-it-for-inline\": \"^0.1.1\",\n    \"markdown-it-linkify-images\": \"^2.0.0\",\n    \"markdown-it-table-of-contents\": \"^0.5.0\",\n    \"markdown-it-task-lists\": \"^2.1.1\",\n    \"postcss\": \"^8.2.2\",\n    \"qs\": \"^6.9.4\",\n    \"remove\": \"^0.1.5\",\n    \"staticrypt\": \"^1.3.2\",\n    \"uglify-es\": \"^3.3.9\",\n    \"url-pattern\": \"^1.0.3\"\n  },\n  \"main\": \".eleventy.js\"\n}\n"
  },
  {
    "path": "password_template.html",
    "content": "<!DOCTYPE html>\n<html class=\"staticrypt-html\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Private Page</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\n    <!-- do not cache this page -->\n    <meta http-equiv=\"cache-control\" content=\"max-age=0\" />\n    <meta http-equiv=\"cache-control\" content=\"no-cache\" />\n    <meta http-equiv=\"expires\" content=\"0\" />\n    <meta http-equiv=\"expires\" content=\"Tue, 01 Jan 1980 1:00:00 GMT\" />\n    <meta http-equiv=\"pragma\" content=\"no-cache\" />\n\n    <style>\n      .staticrypt-hr {\n        margin-top: 20px;\n        margin-bottom: 20px;\n        border: 0;\n        border-top: 1px solid #eee;\n      }\n\n      .staticrypt-page {\n        width: 360px;\n        padding: 8% 0 0;\n        margin: auto;\n        box-sizing: border-box;\n      }\n\n      .staticrypt-form {\n        position: relative;\n        z-index: 1;\n        background: #ffffff;\n        max-width: 360px;\n        margin: 0 auto 100px;\n        padding: 45px;\n        text-align: center;\n        box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2),\n          0 5px 5px 0 rgba(0, 0, 0, 0.24);\n      }\n\n      .staticrypt-form input {\n        outline: 0;\n        background: #f2f2f2;\n        width: 100%;\n        border: 0;\n        margin: 0 0 15px;\n        padding: 15px;\n        box-sizing: border-box;\n        font-size: 14px;\n      }\n\n      .staticrypt-form .staticrypt-decrypt-button {\n        text-transform: uppercase;\n        outline: 0;\n        background: white;\n        width: 100%;\n        border: 0;\n        padding: 15px;\n        color: black;\n        font-size: 14px;\n        cursor: pointer;\n        border: 1px solid black;\n      }\n\n      .staticrypt-form .staticrypt-decrypt-button:hover {\n        background: #E5E7EB;\n      }\n\n      .staticrypt-html {\n        height: 100%;\n      }\n\n      .staticrypt-body {\n        margin-bottom: 1em;\n        background: white;\n        font-family: \"Arial\", sans-serif;\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n      }\n\n      .staticrypt-instructions {\n        margin-top: -1em;\n        margin-bottom: 1em;\n      }\n\n      .staticrypt-title {\n        font-size: 1.5em;\n      }\n\n      .staticrypt-footer {\n        position: fixed;\n        height: 20px;\n        font-size: 16px;\n        padding: 2px;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        margin-bottom: 0;\n      }\n\n      .staticrypt-footer p {\n        margin: 2px;\n        text-align: center;\n        float: right;\n      }\n\n      .staticrypt-footer a {\n        text-decoration: none;\n      }\n\n      #loader {\n        border: 12px solid #f3f3f3;\n        border-radius: 50%;\n        border-top: 12px solid #444444;\n        width: 70px;\n        height: 70px;\n        animation: spin 1s linear infinite;\n      }\n\n      @keyframes spin {\n        100% {\n          transform: rotate(360deg);\n        }\n      }\n\n      .center {\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        margin: auto;\n      }\n    </style>\n    <style>\n      html {\n        display: none !important;\n        opacity: 0;\n      }\n    </style>\n      <script src=\"_includes/assets/inline.js\"></script>\n  </head>\n\n  <body class=\"staticrypt-body\">\n    <div id=\"loader\" class=\"center\"></div>\n    {crypto_tag}\n\n    <script>\n       document.onreadystatechange = function () {\n        if (document.readyState !== \"complete\") {\n          document.querySelector(\"body\").style.visibility = \"hidden\";\n          document.querySelector(\"#loader\").style.visibility = \"visible\";\n        } else {\n          document.querySelector(\"#loader\").style.display = \"none\";\n          document.querySelector(\"body\").style.visibility = \"visible\";\n        }\n      };\n      \n      /**\n       * Decrypt a salted msg using a password.\n       * Inspired by https://github.com/adonespitogo\n       */\n      var keySize = 256;\n      var iterations = 1000;\n      function decrypt(encryptedMsg, pass) {\n        var salt = CryptoJS.enc.Hex.parse(encryptedMsg.substr(0, 32));\n        var iv = CryptoJS.enc.Hex.parse(encryptedMsg.substr(32, 32));\n        var encrypted = encryptedMsg.substring(64);\n\n        var key = CryptoJS.PBKDF2(pass, salt, {\n          keySize: keySize / 32,\n          iterations: iterations,\n        });\n\n        var decrypted = CryptoJS.AES.decrypt(encrypted, key, {\n          iv: iv,\n          padding: CryptoJS.pad.Pkcs7,\n          mode: CryptoJS.mode.CBC,\n        }).toString(CryptoJS.enc.Utf8);\n        return decrypted;\n      }\n\n      window.onload = function () {\n        var form = document.getElementById(\"staticrypt-form\");\n        if (form) {\n          form.addEventListener(\"submit\", function (e) {\n            e.preventDefault();\n            var passphrase = document.getElementById(\"staticrypt-password\")\n              .value;\n            localStorage.setItem(\"passphrase\", passphrase);\n            if (!decryptWithPassphrase(passphrase)) {\n              alert(\"Sorry, that password didn't work!\");\n              return;\n            }\n          });\n        }\n      };\n\n      if (localStorage.getItem(\"passphrase\")) {\n        if (!decryptWithPassphrase(localStorage.getItem(\"passphrase\"))) {\n          localStorage.removeItem(\"passphrase\");\n        }\n      }\n\n      function decryptWithPassphrase(passphrase) {\n        var encryptedMsg = \"{encrypted}\",\n          encryptedHMAC = encryptedMsg.substring(0, 64),\n          encryptedHTML = encryptedMsg.substring(64),\n          decryptedHMAC = CryptoJS.HmacSHA256(\n            encryptedHTML,\n            CryptoJS.SHA256(passphrase).toString()\n          ).toString();\n\n        if (decryptedHMAC !== encryptedHMAC) {\n          return false;\n        }\n\n        var plainHTML = decrypt(encryptedHTML, passphrase);\n        var newHTML = document.open(\"text/html\", \"replace\");\n        newHTML.write(plainHTML);\n        newHTML.close();\n\n        return true;\n      }\n    </script>\n\n    <div class=\"staticrypt-page\">\n      <div class=\"staticrypt-form\">\n        <div class=\"staticrypt-instructions\">\n          <p>🔒 Enter a password to unlock!</p>\n        </div>\n\n        <hr class=\"staticrypt-hr\" />\n\n        <form id=\"staticrypt-form\" action=\"#\" method=\"post\">\n          <input\n            id=\"staticrypt-password\"\n            type=\"password\"\n            name=\"password\"\n            placeholder=\"password\"\n            autofocus\n          />\n          <input\n            type=\"submit\"\n            class=\"staticrypt-decrypt-button\"\n            value=\"ENTER\"\n          />\n        </form>\n      </div>\n    </div>\n    <style>\n      html {\n        display: block !important;\n        opacity: 1;\n      }\n    </style>\n  </body>\n</html>"
  },
  {
    "path": "postcss.config.js",
    "content": "module.exports = {\n  plugins: [\n    require(`tailwindcss`)(`./styles/tailwind.config.js`),\n    require(`autoprefixer`),\n  ],\n};\n"
  },
  {
    "path": "robots.md",
    "content": "---\ntitle: Robots \npermalink: /robots.txt\nlayout: layouts/robots.njk\n---\n"
  },
  {
    "path": "search-index.json.njk",
    "content": "---\npermalink: /search-index.json\n---\n{{ collections.results | search | dump | safe  }}\n\n\n"
  },
  {
    "path": "styles/tailwind.config.js",
    "content": "const autoprefixer = require('autoprefixer');\n\nmodule.exports = {\n  important: true,\n  future: {\n    removeDeprecatedGapUtilities: true,\n    purgeLayersByDefault: true,\n  },\n  purge: {\n    enabled: true,\n    content: [\"_site/**/*.html\"],\n    options: {\n      safelist: [],\n    },\n  },\n  darkMode: 'class',\n  theme: {\n    container: {\n      center: true,\n    },\n    extend: {\n      typography: {\n        DEFAULT: {\n          css: {\n            maxWidth: '100%',\n            a: {\n              color: '#1D4ED8',\n              '&:hover': {\n              color: '#1E3A8A',\n              },\n            },\n            '.prose a.edit, .tag a': {\n              color: '#333',\n              'text-decoration': 'none',\n            },\n            'ul.footer-nav': {\n              '::before': {\n                display: 'none',\n                'text-decoration': 'none',\n              }\n            },\n            'ul.contains-task-list': {\n              '::before': {\n                display: 'none',\n              }\n            },\n            'ul.spacelog': {\n              '::before': {\n                display: 'none',\n              }\n            },\n          },\n        },\n      }\n    },\n  }, \n  variants: {},\n  plugins: [\n    require('@tailwindcss/typography'),\n    require('@tailwindcss/forms'),\n  ],\n}"
  },
  {
    "path": "styles/tailwind.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  \n  /* Set up some default image behavior for nicer images */\n  img {\n    @apply w-auto  shadow-md border-2 border-transparent !important\n  }\n  img:hover {\n    @apply border-2 border-gray-100\n  }\n  /* Overrides for Tailwind Typography prose class */\n  .prose a {\n    @apply dark:text-gray-400\n  }\n  .prose a:hover {\n    @apply dark:text-gray-500\n  }\n  .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 .prose hr, .prose strong {\n    @apply dark:text-gray-400\n  }\n  .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {\n    scroll-margin-top: 3.5em;\n  }\n  .prose pre code {\n    @apply overflow-x-auto !important \n  }\n  .prose .footer-nav a {\n    @apply no-underline !important\n  }\n  .prose ul.contains-task-list,\n  .prose ul.spacelog  {\n    @apply list-none -ml-6 !important;\n  }\n  .prose ul.contains-task-list .task-list-item,\n  .prose ul.spacelog {\n    ::before {\n      @apply hidden !important;\n    }\n  }\n\n  /* Define blockquotes and some standard callout blocks */\n  blockquote {\n    @apply rounded-lg p-4 bg-gray-100 dark:bg-gray-500 border-gray-200 border-l-8 dark:border-gray-700;\n  }\n  .callout {\n    @apply px-8 py-4 mb-4 rounded-lg bg-yellow-50;\n  }\n  .callout, .callout strong, .callout em {\n    @apply dark:bg-gray-400 dark:text-gray-900;\n  }\n  .callout-blue {\n    @apply px-8 py-4 mb-4 rounded-lg bg-blue-50;\n  }\n  .callout-blue, .callout-blue strong, .callout-blue em {\n    @apply dark:text-gray-200 dark:bg-blue-900;\n  }\n  .callout-pink {\n    @apply px-8 py-4 mb-4 rounded-lg bg-pink-50;\n  }\n  .callout-pink, .callout-pink strong, .callout-pink em {\n    @apply dark:text-gray-200 dark:bg-pink-900;\n  }\n  .callout-green {\n    @apply px-8 py-4 mb-4 rounded-lg bg-green-50;\n  }\n  .callout-green, .callout-green strong, .callout-green em {\n    @apply dark:text-gray-200 dark:bg-green-900;\n  }\n  .warning {\n    @apply px-8 py-4 mb-4 rounded-lg bg-red-800 text-gray-50;\n  }\n  .warning, .warning strong, .warning em {\n    @apply text-gray-50 dark:bg-red-900  dark:text-gray-200;\n  }\n\n  /* Overrides for nav/Table of Contents block */\n  nav ul {\n    @apply ml-0 text-gray-500;\n   }\n  nav ul ul {\n   @apply ml-6 text-gray-500;\n  }\n  nav ul li a {\n    @apply mb-1 pt-2 pr-4 pb-1 pl-2 w-full block text-gray-500 dark:text-gray-500;\n  }\n  nav ul li a:hover {\n    @apply text-gray-900 dark:text-gray-400;\n  }\n  nav ul li a.active {\n    @apply font-semibold;\n  }\n  nav.toc ol li {\n    @apply pt-2 !important\n  }\n  nav.toc ol li li {\n    @apply pt-2 ml-4\n  }\n  nav.toc ol li a {\n    @apply text-gray-500\n  }\n  nav.toc ol li a:hover {\n    @apply text-gray-900\n  }\n  .prose .footer-nav a:hover {\n    @apply dark:text-gray-400 !important\n  }\n\n/* Utilities and misc */\n  .adjust  p img, .adjust img, .adjust p iframe, .adjust iframe, .twitter-tweet {\n    @apply shadow-md ml-auto mr-auto  p-2 !important\n  }\n  .adjust  p img:hover, .adjust img:hover {\n    @apply shadow-xl  \n  }\n  .adjust img.button {\n    @apply w-auto  shadow-none !important\n  }\n  .text-align-center {\n    @apply flex justify-center; \n  }\n  .icon-spacer {\n    width: \"24px\";\n  }\n  input {\n   @apply dark:text-gray-400\n  }\n}\n\nblockquote p::before {\n  content: '' !important;\n}\n\nblockquote p::after {\n  content: '' !important;\n}\n\nblockquote>p:first-child {\n  margin-top: 0;\n}\n\nblockquote>p:last-child {\n  margin-bottom: 0;\n}"
  }
]