[
  {
    "path": ".gitignore",
    "content": ".s3cfg\n_site\n_drafts\nbuild\nnshipster.com/articles\nnshipster.com/books\nnshipster.com/training\n.sass-cache\n.vscode\n.jekyll-cache\n.jekyll-metadata\nProcfile\n_functions/search/index.json\nnode_modules\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"collections/en/_posts\"]\n\tpath = collections/en/_posts\n\turl = https://github.com/NSHipster/articles.git\n\tbranch = master\n\tignore = all\n\tupdate = merge\n[submodule \"collections/zh-Hans/_posts\"]\n\tpath = collections/zh-Hans/_posts\n\turl = https://github.com/NSHipster/articles-zh-Hans.git\n\tbranch = master\n\tignore = all\n\tupdate = merge\n[submodule \"collections/es/_posts\"]\n\tpath = collections/es/_posts\n\turl = https://github.com/NSHipster/articles-es.git\n\tbranch = master\n\tignore = all\n\tupdate = merge\n[submodule \"collections/ko/_posts\"]\n\tpath = collections/ko/_posts\n\turl = https://github.com/NSHipster/articles-ko.git\n\tbranch = master\n\tignore = all\n\tupdate = merge\n[submodule \"collections/fr/_posts\"]\n\tpath = collections/fr/_posts\n\turl = https://github.com/NSHipster/articles-fr.git\n\tbranch = master\n\tignore = all\n\tupdate = merge\n"
  },
  {
    "path": ".ruby-version",
    "content": "2.7.5\n"
  },
  {
    "path": ".tool-versions",
    "content": "ruby 2.7.5\n"
  },
  {
    "path": ".well-known/brave-payments-verification.txt",
    "content": "This is a Brave Payments publisher verification file.\n\nDomain: nshipster.com\nToken: 9427d793d5eb646c66ff42e31086f6e792c31f252ba241ce213f98d6dd1ddfce\n"
  },
  {
    "path": ".well-known/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo src=\"/mstile-150x150.png\"/>\n            <TileColor>#f8f7f5</TileColor>\n        </tile>\n    </msapplication>\n</browserconfig>\n"
  },
  {
    "path": ".well-known/humans.txt",
    "content": "---\nlayout: null\npermalink: /humans.txt\n---\n\n/* TEAM */\n\nManaging Editor: Mattt\nSite: https://mat.tt\nContact: mattt [at] nshipster.com\nTwitter: @mattt\nLocation: Portland, OR, United States\n\n/* SITE */\n\nLast update: {{ site.time | date: \"%Y/%-m/%-d\" }}\nLanguage: {{ site.lang }}\nStandards: HTML5, CSS3, WAI-ARIA\nComponents: Zepto\nSoftware: Jekyll\nIDE: Visual Studio Code\n"
  },
  {
    "path": ".well-known/robots.txt",
    "content": "---\nlayout: null\npermalink: /robots.txt\n---\n\nUser-agent: *\nAllow: /\n\nSitemap: {{ site.url }}/sitemap.xml\n"
  },
  {
    "path": ".well-known/site.webmanifest",
    "content": "{\n    \"name\": \"NSHipster\",\n    \"short_name\": \"NSHipster\",\n    \"icons\": [{\n            \"src\": \"/android-chrome-192x192.png\",\n            \"sizes\": \"192x192\",\n            \"type\": \"image/png\"\n        },\n        {\n            \"src\": \"/android-chrome-384x384.png\",\n            \"sizes\": \"384x384\",\n            \"type\": \"image/png\"\n        }\n    ],\n    \"theme_color\": \"#f8f7f5\",\n    \"background_color\": \"#f8f7f5\",\n    \"display\": \"standalone\"\n}\n"
  },
  {
    "path": "404.md",
    "content": "---\nlayout: error\ntitle: NSError 404 - NSHipster\npermalink: 404.html\n---\n\n```swift\nlet domain = \"{{ site.url | host }}\"\nlet code = 404\nlet userInfo = [\n    NSLocalizedDescriptionKey:\n        \"Requested page is too obscure, and probably does not exist.\",\n    NSLocalizedRecoverySuggestionErrorKey:\n        \"Go back to the mainstream site.\"\n]\n\nthrow NSError(domain: domain, code: code, userInfo: userInfo)\n```\n\n```objc\nNSString *domain = @\"{{ site.url | host }}\";\nNSInteger code = 404;\nNSDictionary *userInfo = @{\n    NSLocalizedDescriptionKey:\n        @\"Requested page is too obscure, and probably does not exist.\",\n    NSLocalizedRecoverySuggestionErrorKey:\n        @\"Go back to the mainstream site.\"\n};\n\nNSError *error = [[NSError alloc] initWithDomain:domain\n                                            code:code\n                                        userInfo:userInfo];\n```\n"
  },
  {
    "path": "Gemfile",
    "content": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\ngem 'jekyll'\ngem 'rack', '>= 2.0.6'\n\ngem 'sprockets', '~> 4.0.beta'\ngem 'uglifier', '~> 4.0'\n\ngem 'kramdown'\n\ngem 'rouge', git: 'https://github.com/NSHipster/rouge.git',\n             branch: 'master'\n\ngem 'nokogiri'\ngem 'sassc'\ngem 'ffi', '1.16.3'\n\ngem 'twitter_cldr'\n\ngroup :jekyll_plugins do\n  gem 'jekyll-assets', git: 'https://github.com/envygeeks/jekyll-assets.git',\n                       branch: 'master'\n  gem 'jekyll-include-cache'\n  gem 'jekyll-scholar'\n  gem 'jekyll-tidy'\nend\n\ngroup :development do\n  gem 'foreman'\n  gem 'rake'\nend\n\n# Windows does not include zoneinfo files, so bundle the tzinfo-data gem\ngem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright 2012 – 2025 NSHipster (https://nshipster.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, 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\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# NSHipster.com\n\n[NSHipster](https://nshipster.com) is a journal of the overlooked bits in\nSwift, Objective-C and Cocoa.\nUpdated weekly.\n\nThis repository hosts the source code that generates and deploys\n[NSHipster.com](https://nshipster.com) and its translations.\nFor the articles themselves,\nsee [this repository](https://github.com/nshipster/articles).\n\n---\n\n## Requirements\n\n- Git 2.16.2+\n- Ruby 2.4.3+\n- [Bundler](https://bundler.io)\n\n## Running Locally\n\nFirst, clone the repository by opening Terminal.app\nand running the following commands:\n\n```terminal\n$ git clone git@github.com:NSHipster/nshipster.com.git\n$ cd nshipster.com\n```\n\nNext, clone the articles submodules\nwith the following commands:\n\n```terminal\n$ git submodule update --init --remote --merge\n```\n\nNSHipster is built using\n[Jekyll](https://github.com/jekyll/jekyll),\na blog-aware, static site generator in Ruby.\n\nDownload and update the project dependencies with Bundler\nusing the command:\n\n```terminal\n$ bundle install\n```\n\nTo run the site locally,\nyou must specify the configuration file\ncorresponding to the NSHipster website you'd like to build\n(i.e. NSHipster.com, NSHipster.cn, etc.).\nYou can run the site locally with the following commands:\n\n```terminal\n$ bundle exec jekyll serve --config _config/default.yml,_config/$DOMAIN.yml --trace\n```\n\nNow open the server address in a web browser to see a local copy of the site\n(by default, Jekyll serves to localhost on port 4000):\n\n```terminal\n$ open http://localhost:4000\n```\n\n## Deploying\n\nNSHipster.com is hosted by [Netlify](https://netlify.com).\nThe site is configured with continuous deployment\nsuch that any push to the `master` branch on this repository\nautomatically triggers a build and deploys the site, if successful.\n\nUsers with Push access can deploy the site by running the following command:\n\n```terminal\n$ git push origin master\n```\n\nYou can monitor the status of a deploy in real-time\n[on this dashboard](https://app.netlify.com/sites/nshipster/deploys/).\n\n## Contact\n\nFollow NSHipster on Twitter\n([@NSHipster](https://twitter.com/NSHipster))\n\n## License\n\nAll code is published under the\n[MIT License](https://opensource.org/licenses/MIT).\n\nAll content is released under the\n[Creative Commons BY-NC License](https://creativecommons.org/licenses/by-nc/4.0/).\n\nNSHipster® and the NSHipster Logo\nare registered trademarks of Read Evaluate Press, LLC.\n"
  },
  {
    "path": "_bibliography/references.bib",
    "content": "---\n---\n\n@article{de_montjoye_2013,\n    title = {Unique in the {Crowd}: {The} privacy bounds of human mobility},\n    volume = {3},\n    copyright = {2013 Nature Publishing Group},\n    issn = {2045-2322},\n    shorttitle = {Unique in the {Crowd}},\n    url = {https://www.nature.com/articles/srep01376},\n    doi = {10.1038/srep01376},\n    abstract = {We study fifteen months of human mobility data for one and a half million individuals and find that human mobility traces are highly unique. In fact, in a dataset where the location of an individual is specified hourly, and with a spatial resolution equal to that given by the carrier's antennas, four spatio-temporal points are enough to uniquely identify 95\\% of the individuals. We coarsen the data spatially and temporally to find a formula for the uniqueness of human mobility traces given their resolution and the available outside information. This formula shows that the uniqueness of mobility traces decays approximately as the 1/10 power of their resolution. Hence, even coarse datasets provide little anonymity. These findings represent fundamental constraints to an individual's privacy and have important implications for the design of frameworks and institutions dedicated to protect the privacy of individuals.},\n    language = {en},\n    urldate = {2019-10-30},\n    journal = {Scientific Reports},\n    author = {de Montjoye, Yves-Alexandre and Hidalgo, César A. and Verleysen, Michel and Blondel, Vincent D.},\n    month = mar,\n    year = {2013},\n    pages = {1376}\n}\n\n@article {sweeney_2000,\n    title = {Simple Demographics Often Identify People Uniquely},\n    journal = {Carnegie Mellon University, Data Privacy},\n    year = {2000},\n    type = {Working paper},\n    url = {http://dataprivacylab.org/projects/identifiability/},\n    author = {Sweeney, Latanya}\n}\n\n@inproceedings{zhang_2019,\n    author = {Zhang, Jiexin and Beresford, Alastair R. and Sheret, Ian},\n    title = {SensorID: Sensor Calibration Fingerprinting for Smartphones},\n    booktitle = {Proceedings of the 40th IEEE Symposium on Security and Privacy (SP)},\n    year = {2019},\n    month = {May},\n    publisher = {IEEE}\n}\n\n@inproceedings{olejnik_2015,\n author = {Olejnik, \\Lukasz and Acar, Gunes and Castelluccia, Claude and Diaz, Claudia},\n title = {The Leaking Battery},\n booktitle = {Revised Selected Papers of the 10th International Workshop on Data Privacy Management, and Security Assurance - Volume 9481},\n year = {2016},\n isbn = {978-3-319-29882-5},\n pages = {254--263},\n numpages = {10},\n url = {http://dx.doi.org/10.1007/978-3-319-29883-2_18},\n doi = {10.1007/978-3-319-29883-2_18},\n acmid = {2979465},\n publisher = {Springer-Verlag New York, Inc.},\n address = {New York, NY, USA},\n}\n\n@inproceedings{inproceedings,\nauthor = {rizzo_2016},\nyear = {2016},\nmonth = {07},\npages = {97-104},\ntitle = {Content-preserving Text Watermarking through Unicode Homoglyph Substitution},\ndoi = {10.1145/2938503.2938510}\n}\n\n@ARTICLE{artz_2001,\nauthor={D. {Artz}},\njournal={IEEE Internet Computing},\ntitle={Digital steganography: hiding data within data},\nyear={2001},\nvolume={5},\nnumber={3},\npages={75-80},\ndoi={10.1109/4236.935180},\nISSN={},\nmonth={May},}\n\n@inproceedings{weinberg_2018,\n author = {Weinberg, Zachary and Cho, Shinyoung and Christin, Nicolas and Sekar, Vyas and Gill, Phillipa},\n title = {How to Catch when Proxies Lie: Verifying the Physical Locations of Network Proxies with Active Geolocation},\n booktitle = {Proceedings of the Internet Measurement Conference 2018},\n series = {IMC '18},\n year = {2018},\n isbn = {978-1-4503-5619-0},\n location = {Boston, MA, USA},\n pages = {203--217},\n numpages = {15},\n url = {http://doi.acm.org/10.1145/3278532.3278551},\n doi = {10.1145/3278532.3278551},\n acmid = {3278551},\n publisher = {ACM},\n address = {New York, NY, USA},\n keywords = {active geolocation, network proxies, virtual private networks},\n}\n\n@inproceedings{meli_2019,\n author = {Meli, Michael and McNiece, Matthew R. and Reaves, Bradley},\n title = {How Bad Can It Git? Characterizing Secret Leakage in Public GitHub Repositories},\n booktitle = {Proceedings of the NDSS Symposium 2019},\n series = {NDSS’19},\n year = {2019},\n location = {San Diego, CA, USA},\n url = {https://www.ndss-symposium.org/ndss-paper/how-bad-can-it-git-characterizing-secret-leakage-in-public-github-repositories/},\n}\n\n@INPROCEEDINGS{wen_2018,\nauthor={H. {Wen} and J. {Li} and Y. {Zhang} and D. {Gu}},\nbooktitle={2018 25th Asia-Pacific Software Engineering Conference (APSEC)},\ntitle={An Empirical Study of SDK Credential Misuse in iOS Apps},\nyear={2018},\nvolume={},\nnumber={},\npages={258-267},\nkeywords={data privacy;Internet;mobile computing;software engineering;mobile developers;SDK credential misuse issue;iOS platform;software development kit;popular iOS apps;app token;APP ID;serious security threats;typical SDK misuses;app developers;second-tier problem;security issues;mobile payment;push notification;third-party SDKs;web-based mobile apps;misuse case;popular mobile SDKs;Binary codes;Web services;Authentication;Tools;Performance analysis;iOS apps, Third-party SDKs, Binary code anal ysis, Credential exposure},\ndoi={10.1109/APSEC.2018.00040},\nISSN={},\nmonth={Dec},}\n\n@INPROCEEDINGS{wang_2018,\nauthor={P. {Wang} and D. {Wu} and Z. {Chen} and T. {Wei}},\nbooktitle={2018 IEEE/ACM 40th International Conference on Software Engineering: Software Engineering in Practice Track (ICSE-SEIP)},\ntitle={Protecting Million-User iOS Apps with Obfuscation: Motivations, Pitfalls, and Experience},\nyear={2018},\nvolume={},\nnumber={},\npages={235-244},\nkeywords={Internet;mobile computing;reverse engineering;security of data;app vendors;software obfuscation;mobile app;multiple commercial iOS apps;million-user iOS apps;app-provided services;Web-based services whose important program logic;Software;Reverse engineering;Security;Servers;Business;Software protection;obfuscation;software protection;reverse engineering;mobile;iOS},\ndoi={},\nISSN={},\nmonth={May},}\n"
  },
  {
    "path": "_config/default.yml",
    "content": "title: NSHipster\npermalink: /:title/\n\ntwitter: 629523445\nfacebook: 418545184954768\nissn: 2373-9800\n\ndomains:\n  en: https://nshipster.com\n\nauthor:\n  name: Mattt\n  email: mattt@nshipster.com\n  url: /authors/mattt\n\nmarkdown: NSHipsterProcessor\nhighlighter: rouge\n\nkramdown:\n  parse_block_html: true\n  parse_span_html: true\n\nfuture: true\n\nstrict_front_matter: true\n\ndefaults:\n  - scope:\n      path: \"\"\n    values:\n      layout: \"default\"\n  - scope:\n      path: \"\"\n      type: \"authors\"\n    values:\n      layout: \"author\"\n  - scope:\n      path: \"\"\n      type: \"translators\"\n    values:\n      layout: \"translator\"\n  - scope:\n      path: \"\"\n      type: \"posts\"\n    values:\n      layout: \"post\"\n\ngroups:\n  - Cocoa\n  - Swift\n  - Xcode\n  - Open Source\n  - Miscellaneous\n  - Trivia\n  - Objective-C\n\ninclude: [\".well-known\"]\n\nexclude:\n  - README*\n  - LICENSE*\n  - Gemfile*\n  - Procfile\n  - Rakefile\n  - rakelib/\n  - netlify.toml\n  - _redirects\n  - _functions/\n  - vendor/\n  - node_modules\n\nassets:\n  source_maps: false\n  compression: true\n  defaults:\n    js: { integrity: true }\n    css: { integrity: true }\n    img: { integrity: true }\n\njekyll_tidy:\n  exclude:\n    - robots.txt\n    - humans.txt\n"
  },
  {
    "path": "_config/nshipster.cn.yml",
    "content": "url: https://nshipster.cn\nlang: zh-Hans\n\ndescription: >-\n  **NSHipster** 关注被忽略的 Objective-C、Swift 和 Cocoa 特性。\ntimezone: Asia/Shanghai\n\ncollections_dir: collections/zh-Hans\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  translators:\n    output: true\n    permalink: /translators/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nshipster.co.kr.yml",
    "content": "url: https://nshipster.co.kr\nlang: ko-KR\n\ndescription: >-\n  **NSHipster**는 간과 된 비트의 저널입니다\n  Objective-C, Swift 및 Cocoa에서.\n\ntimezone: Asia/Seoul\n\ncollections_dir: collections/ko\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  translators:\n    output: true\n    permalink: /translators/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nshipster.com.ru.yml",
    "content": "url: https://nshipster.com.ru\nlang: ru-RU\n\ndescription: >-\n  **NSHipster** это журнал пропущенных бит в\n  Objective-C, Swift и Cocoa.\ntimezone: Europe/Moscow\n\ncollections_dir: collections/en\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  translators:\n    output: true\n    permalink: /translators/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nshipster.com.yml",
    "content": "url: https://nshipster.com\nlang: en-US\n\ndescription: >-\n  **NSHipster** is a journal of the overlooked bits\n  in Objective-C, Swift, and Cocoa.\ntimezone: America/Los_Angeles\n\ncollections_dir: collections/en\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nshipster.es.yml",
    "content": "url: https://nshipster.es\nlang: es-ES\n\ndescription: >-\n  **NSHipster** es una publicación de los bits pasados por alto\n  en Objective-C, Swift y Cocoa.\ntimezone: Europe/Madrid\n\ncollections_dir: collections/es\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  translators:\n    output: true\n    permalink: /translators/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nshipster.fr.yml",
    "content": "url: https://nshipster.fr\nlang: fr-FR\n\ndescription: >-\n  **NSHipster** est une publication qui s'intéresse aux\n  parties obscures de l'Objective-C, de Swift et de Cocoa.\ntimezone: Europe/Paris\n\ncollections_dir: collections/fr\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  translators:\n    output: true\n    permalink: /translators/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_config/nsmutablehipster.com.yml",
    "content": "title: NSMutableHipster\nurl: https://nsmutablehipster.com\nlang: en-US\n\ndescription: >-\n  **NSHipster** is a journal of the overlooked bits\n  in Objective-C, Swift, and Cocoa.\ntimezone: America/Los_Angeles\n\ncollections_dir: collections/en\ncollections:\n  authors:\n    output: true\n    permalink: /authors/:path/\n  books:\n    output: false\n"
  },
  {
    "path": "_functions/search/package.json",
    "content": "{\n  \"name\": \"nshipster-netlify-functions\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"search.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"lunr\": \"^2.3.8\"\n  }\n}\n"
  },
  {
    "path": "_functions/search/search.js",
    "content": "const fs = require(\"fs\");\nconst lunr = require(\"lunr\");\n\nconst json = JSON.parse(fs.readFileSync(require.resolve(\"./index.json\")));\nvar index = lunr(function() {\n  this.ref(\"url\");\n  this.field(\"title\", { boost: 10 });\n  this.field(\"category\");\n  this.field(\"excerpt\");\n\n  json.forEach(function(doc) {\n    console.log(doc);\n    this.add(doc);\n  }, this);\n});\n\nexports.handler = function(event, context, callback) {\n  const query = event.queryStringParameters.q;\n\n  if (!query || query === \"\") {\n    callback(null, {\n      statusCode: 400,\n      body: JSON.stringify({ message: \"Invalid query\" })\n    });\n  } else {\n    const results = index.search(query);\n    callback(null, {\n      statusCode: 200,\n      body: JSON.stringify(results)\n    });\n  }\n};\n"
  },
  {
    "path": "_i18n/en-US.yml",
    "content": "format:\n  date: \"%B %-d<sup>%o</sup>, %Y\"\n\nthis_week: This Week...\ncontinue_reading: Continue Reading\nrecent_articles: Recent Articles\npublications: Recommended Reading\npopular_articles: Popular Articles\ncontributors: Contributors\ntranslated_into: \"This article has been translated into:\"\n\nwritten_by: Written by\ntranslated_by: Translated by\nrevised: revised\n\nnext_article: Next Article\nrelated_articles: Related Articles\n\narticles: Articles\n\ncorrections: Questions? Corrections? <a href=\"https://twitter.com/NSHipster\">@NSHipster</a> or <a href=\"https://github.com/NSHipster/articles\">on GitHub</a>.\nlicense: NSHipster.com is released under a <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\" rel=\"license\">Creative Commons BY-NC License</a>.\n"
  },
  {
    "path": "_i18n/es-ES.yml",
    "content": "format:\n  date: \"%-d/%-m/%Y\"\n\nthis_week: Esta semana...\ncontinue_reading: Sigue leyendo\nrecent_articles: Artículos recientes\npublications: Libros\npopular_articles: Artículos populares\ncontributors: Colaboradores\ntranslated_into: \"Este artículo ha sido traducido a:\"\n\nwritten_by: Escrito por\ntranslated_by: Traducido por\nrevised: revisado\n\nnext_article: Artículo siguiente\nrelated_articles: Artículos relacionados\n\narticles: Artículos\n\ncorrections: ¿Preguntas? Correcciones? <a href=\"https://twitter.com/NSHipster\">@NSHipster</a> y <a href=\"https://github.com/NSHipster/articles\">on GitHub</a>.\nlicense: NSHipster.com tiene licencia de <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\" rel=\"license\">Creative Commons BY-NC License</a>.\n"
  },
  {
    "path": "_i18n/fr-FR.yml",
    "content": "format:\n  date: \"%-d/%-m/%Y\"\n\nthis_week: Cette semaine...\ncontinue_reading: Lire la suite\nrecent_articles: Articles récents\npublications: Livres\npopular_articles: Articles populaires\ncontributors: Contributeurs\nall_articles: Tous les articles\ntranslated_into: \"Cet article a été traduit en :\"\n\nwritten_by: Écrit par\ntranslated_by: Traduit par\nrevised: modifié\n\nnext_article: Article suivant\nrelated_articles: Articles connexes\n\narticles: Articles\n\ncorrections: Des questions ? Des corrections ? <a href=\"https://twitter.com/NSHipster\">@NSHipster</a> et <a href=\"https://github.com/NSHipster/articles\">sur GitHub</a>.\nlicense: NSHipster est publié sous licence <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\" rel=\"license\">Creative Commons BY-NC License</a>.\n"
  },
  {
    "path": "_i18n/ko-KR.yml",
    "content": "format:\n  date: \"%Y년 %-m월 %-d일\"\n\nthis_week: 이번 주\ncontinue_reading: 더 읽기\nrecent_articles: 최근 기사\npublications: 책\npopular_articles: 인기 기사\ncontributors: 기여자\nall_articles: 모든 기사\ntranslated_into: \"이 기사는 다음과 같이 번역되었습니다 :\"\n\nwritten_by: \"작성자 :\"\ntranslated_by: \"번역자 :\"\nrevised: 개정 된\n\nnext_article: 다음 글\nrelated_articles: 관련 글\n\narticles: 기사\n\ncorrections: 궁금하거나 잘못된 내용이 있나요? <a href=\"https://twitter.com/NSHipster\">@NSHipster</a> 또는 <a href=\"https://github.com/NSHipster/articles\">GitHub</a> 에 알려주세요.\nlicense: NSHipster는 <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\" rel=\"license\">Creative Commons BY-NC</a>에 따라 라이센스가 부여됩니다.\n"
  },
  {
    "path": "_i18n/ru-RU.yml",
    "content": "format:\n  date: \"%-d.%-m.%Y\"\n\nthis_week: На этой неделе...\ncontinue_reading: Продолжить чтение\nrecent_articles: Последние статьи\npublications: Книги\npopular_articles: Популярные статьи\ncontributors: Авторы\ntranslated_into: \"Данная статья переведена на:\"\n\nwritten_by: Написано\ntranslated_by: Переведено\nrevised: пересмотренный\n\nnext_article: Следующая статья\nrelated_articles: Статьи по Теме\n\narticles: Статьи\n\ncorrections: Вопросов? Поправки? <a href=\"https://twitter.com/NSHipster\">@NSHipster</a> или <a href=\"https://github.com/NSHipster/articles\">на GitHub</a>.\nlicense: NSHipster выпущен под лицензией <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\" rel=\"license\">Лицензия Creative Commons BY-NC</a>.\n"
  },
  {
    "path": "_i18n/zh-Hans.yml",
    "content": "format:\n  date: \"%Y年%-m月%-d日\"\n\nthis_week: 本周发布\ncontinue_reading: 继续阅读\nrecent_articles: 最近的文章\npublications: 书籍\npopular_articles: 热门文章\ncontributors: 贡献者\ntranslated_into: \"本文已翻译为：\"\n\nwritten_by: 作者\ntranslated_by: 翻译者\nrevised: 有改动\n\nnext_article: 下一篇文章\nrelated_articles: 相关文章\n\narticles: 文章\n\ncorrections: \" \"\nlicense: 除非另有声明、本网站采用知识共享「<a href=\"http://creativecommons.org/licenses/by-nc/3.0/cn/\" rel=\"license\">署名-非商业性使用 3.0 中国大陆</a>」许可协议授权。\n"
  },
  {
    "path": "_includes/book.html",
    "content": "{% assign book = site.books | where:\"name\", include.book | first %}\n\n<div id=\"{{ book.name }}\" class=\"book\">\n    <a href=\"{{ book.book_url }}\" title=\"{{ book.title }}\" rel=\"noopener noreferrer\" target=\"_blank\">\n      <img src=\"{% asset \"{{ book.image }}\" @path %}\" class=\"cover\" alt=\"{{ book.title }}\" />\n    </a>\n\n    {% include json-ld/book.html %}\n</div>\n"
  },
  {
    "path": "_includes/contributor.html",
    "content": "{% case include.role %}\n{% when 'author' %}\n  {% assign contributor = site.authors | where:\"name\", page.author | first %}\n{% when 'translator' %}\n  {% assign contributor = site.translators | where:\"name\", page.translator | first %}\n{% endcase %}\n\n<div class=\"contributor\">\n    {% case include.role %}\n    {% when 'author' %}\n        <small>{% t written_by %}</small>\n    {% when 'translator' %}\n        <small>{% t translated_by %}</small>\n    {% endcase %}\n\n    {% if contributor %}\n        {% if contributor.image %}\n            <img class=\"avatar\" alt=\"{{ contributor.name }}\" src=\"{% asset \"{{ contributor.image }}\" @path %}\" draggable=\"false\"/>\n        {% else %}\n            <img class=\"avatar\" src=\"//0.gravatar.com/avatar/{{ contributor.gravatar }}?size=300\" draggable=\"false\"/>\n        {% endif %}\n\n        <div class=\"details\">\n            <span><a href=\"{{ contributor.url }}\">{{ contributor.name }}</a></span>\n\n            {{ contributor.content | markdownify }}\n        </div>\n    {% endif %}\n</div>\n"
  },
  {
    "path": "_includes/json-ld/article.html",
    "content": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"{{ page.title | strip_html | strip }}\",\n  \"description\": \"{{ page.excerpt | markdownify | strip_html | strip }}\",\n  \"image\": \"{{ '/logo.png' | absolute_url }}\",\n  \"datePublished\": \"{{ page.date | date_to_xmlschema }}\",\n  \"dateModified\": \"{{ page.last_revised_on | date_to_xmlschema }}\",\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"{{ site.url }}\"\n  },\n  \"author\": {\n    \"@type\": \"Person\",\n    \"name\": \"Mattt\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"NSHipster\",\n    \"logo\": {\n      \"@type\": \"ImageObject\",\n      \"url\": \"{{ '/logo.png' | absolute_url }}\"\n    }\n  },\n  \"speakable\": {\n    \"@type\": \"SpeakableSpecification\",\n    \"xpath\": [\n        \"/html/head/title\",\n        \"/html/head/meta[@name='description']/@content\"\n    ]\n  }\n}\n</script>\n"
  },
  {
    "path": "_includes/json-ld/book.html",
    "content": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Book\",\n  \"author\": {\n    \"@type\": \"Person\",\n    \"name\": \"Mattt\"\n  },\n  \"bookFormat\": \"https://schema.org/EBook\",\n  \"datePublished\": \"{{ book.date }}\",\n  \"image\": \"{% asset '{{ book.image }}' @path %}\",\n  \"inLanguage\": \"English\",\n  \"isbn\": \"{{ book.isbn }}\",\n  \"name\": \"{{ book.title | strip_html | strip }}\",\n  \"description\": \"{{ book.summary | markdownify | strip_html | strip }}\",\n  \"numberOfPages\": \"{{ book.number_of_pages }}\",\n  \"offers\": {\n    \"@type\": \"Offer\",\n    \"availability\": \"https://schema.org/InStock\",\n    \"price\": \"{{ book.price }}\",\n    \"priceCurrency\": \"USD\",\n    \"url\": \"{{ book.book_url }}\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"Read Evaluate Press, LLC\"\n  }\n}\n</script>\n"
  },
  {
    "path": "_includes/json-ld/breadcrumblist.html",
    "content": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [{\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"item\": {\n        \"@id\": \"{{ site.url }}\",\n        \"name\": \"Articles\"\n      }\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"item\": {\n        \"@id\": \"{{ page.url | absolute_url }}\",\n        \"name\": \"{{ page.title | strip_html }}\"\n      }\n    }\n  ]\n}\n</script>\n"
  },
  {
    "path": "_includes/json-ld/organization.html",
    "content": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Organization\",\n  \"name\": \"NSHipster\",\n  \"legalName\": \"NSHipster, LLC\",\n  \"url\": \"https://nshipster.com\",\n  \"logo\": {\n      \"@type\": \"ImageObject\",\n      \"url\": \"{{ '/logo.png' | absolute_url }}\"\n  },\n  \"foundingDate\": \"2012-07-07\",\n  \"founders\": [{\n    \"@type\": \"Person\",\n    \"name\": \"Mattt\"\n  }],\n  \"sameAs\": [\n    \"https://twitter.com/nshipster\",\n    \"https://github.com/nshipster\"\n  ]\n}\n</script>\n"
  },
  {
    "path": "_includes/json-ld/website.html",
    "content": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"WebSite\",\n  \"url\": \"{{ site.url }}\",\n  \"name\": \"{{ site.title | strip_html | strip }}\",\n  \"author\": {\n    \"@type\": \"Person\",\n    \"name\": \"Mattt\"\n  },\n  \"description\": \"{{ site.description | markdownify | strip_html | strip }}\",\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"NSHipster\",\n    \"logo\": {\n      \"@type\": \"ImageObject\",\n      \"url\": \"{{ '/logo.png' | absolute_url }}\"\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "_includes/promo.html",
    "content": "{% assign book = site.books | where:\"name\", include.book | first %}\n\n<section id=\"promotion\"{% if include.home %} class=\"home\"{% endif %}>\n    <small>Now Available</small>\n\n    <article>\n    {% include book.html book=book.name %}\n    <div>\n        <span class=\"price\">\n            $9+\n        </span>\n        <h3><a href=\"{{ book.book_url }}\" rel=\"noopener\">{{ book.sub_title }}</a></h3>\n        <h4>{{ book.edition }}</h4>\n        {{ book.summary | markdownify }}\n\n        <a class=\"buy\" href=\"{{ book.book_url }}\" rel=\"noopener\">Buy Now on Gumroad</a>\n    </div>\n    </article>\n</section>\n"
  },
  {
    "path": "_layouts/author.html",
    "content": "---\nlayout: default\n---\n\n{% assign author = page %}\n{% capture date_format %}{% t format.date %}{% endcapture %}\n\n<article class=\"author\">\n  <header role=\"heading\">\n    {% if author.image %}\n      <img class=\"avatar\" alt=\"{{ author.name }}\" src=\"{% asset \"{{ author.image }}\" @path %}\" draggable=\"false\"/>\n    {% elsif author.gravatar %}\n      <img class=\"avatar\" src=\"//0.gravatar.com/avatar/{{ author.gravatar }}?size=300\" draggable=\"false\"/>\n    {% endif %}\n    <h1>{{ author.name }}</h1>\n\n    {{ author.content | markdownify }}\n  </header>\n\n  <section class=\"archive\">\n    <h1>{% t articles %}</h1>\n\n    <ol>\n    {% for post in site.posts %}\n      {% if post.author == author.name or post.authors contains author.name %}\n        <li>\n          <a href=\"{{ post.url }}\" title=\"{{ post.title }}\" class=\"title\">{{ post.title }}</a>\n          <time datetime=\"{{ post.date | date_to_xmlschema }}\">{{ post.date | date: date_format }}</time>\n\n          {{ post.excerpt | markdownify }}\n        </li>\n      {% endif %}\n    {% endfor %}\n    </ol>\n  </section>\n</article>\n\n"
  },
  {
    "path": "_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ site.lang }}\">\n<head>\n  <meta charset=\"utf-8\"/>\n  {% if page.id %}\n    <title>{{ page.title | strip_html | escape | strip }} - {{ site.title }}</title>\n    <meta name=\"description\" content=\"{{ page.excerpt | markdownify | strip_html }}\"/>\n    <meta name=\"revisit-after\" content=\"1 month\"/>\n  {% else %}\n    <title>{{ page.title | strip_html | escape | strip }}</title>\n    <meta name=\"description\" content=\"{{ site.description | markdownify | strip_html }}\"/>\n    <meta name=\"revisit-after\" content=\"7 days\"/>\n  {% endif %}\n\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\"/>\n  <meta name=\"format-detection\" content=\"telephone=no\"/>\n  <meta name=\"color-scheme\" content=\"light dark\"/>\n\n  <link rel=\"alternate\" type=\"application/atom+xml\" title=\"{{ site.title }} Atom Feed\" href=\"/feed.xml\"/>\n\n  <link rel=\"preload\" type=\"font/woff2\" as=\"font\" href=\"{% asset Merriweather-Regular.woff2 @path %}\" crossorigin=\"anonymous\" />\n  <link rel=\"preload\" type=\"font/woff2\" as=\"font\" href=\"{% asset Merriweather-Bold.woff2 @path %}\" crossorigin=\"anonymous\" />\n  <link rel=\"preload\" type=\"font/woff2\" as=\"font\" href=\"{% asset Merriweather-Italic.woff2 @path %}\" crossorigin=\"anonymous\" />\n  <link rel=\"preload\" type=\"font/woff2\" as=\"font\" href=\"{% asset CreativeCommonsSymbols.woff2 @path %}\" crossorigin=\"anonymous\" />\n\n  {% asset \"screen.css\" @inline %}\n\n  <link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\"/>\n  <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\"/>\n  <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\"/>\n  <link rel=\"manifest\" href=\"/site.webmanifest\"/>\n  <link rel=\"mask-icon\" href=\"/safari-pinned-tab.svg\" color=\"#292724\"/>\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-title\" content=\"NSHipster\"/>\n  <meta name=\"application-name\" content=\"NSHipster\"/>\n  <meta name=\"msapplication-TileColor\" content=\"#f8f7f5\"/>\n  <meta name=\"theme-color\" content=\"#f8f7f5\"/>\n\n  <link rel=\"author\" type=\"text/plain\" href=\"/humans.txt\"/>\n  <link rel=\"license\" href=\"https://creativecommons.org/licenses/by-nc/4.0/\"/>\n\n  <meta name=\"twitter:card\" content=\"summary\"/>\n  <meta name=\"twitter:site\" content=\"@NSHipster\"/>\n  {% if author and author.twitter %}\n  <meta name=\"twitter:creator\" content=\"@{{ author.twitter }}\"/>\n  {% endif %}\n  {% if page.id %}\n    <meta name=\"twitter:title\" content=\"{{ page.title }}\"/>\n    <meta name=\"twitter:description\" content=\"{{ page.excerpt | markdownify | strip_html | escape }}\"/>\n    <meta name=\"twitter:label1\" value=\"Category\" />\n    <meta name=\"twitter:data1\" value=\"{{ page.category }}\" />\n  {% else %}\n    <meta name=\"twitter:title\" content=\"{{ site.title }}\"/>\n    <meta name=\"twitter:description\" content=\"{{ site.description | markdownify | strip_html | escape }}\"/>\n  {% endif %}\n  <meta name=\"twitter:account_id\" content=\"{{ site.twitter }}\"/>\n\n  <meta property=\"og:site_name\" content=\"{{ site.title }}\"/>\n  <meta property=\"og:image\" content=\"{{ '/logo.png' | absolute_url }}\"/>\n  {% if page.id %}\n    <meta property=\"og:type\" content=\"article\"/>\n    <meta property=\"og:title\" content=\"{{ page.title }}\"/>\n    <meta property=\"og:url\" content=\"{{ page.url | absolute_url }}\"/>\n    <meta property=\"og:description\" content=\"{{ page.excerpt | markdownify | strip_html | escape }}\"/>\n    <meta property=\"article:published_time\" content=\"{{ page.date | date_to_xmlschema }}\"/>\n    <meta property=\"article:modified_time\" content=\"{{ site.time | date_to_xmlschema }}\"/>\n    <meta property=\"article:tag\" content=\"{{ page.categories | join: ',' }}\"/>\n    <meta property=\"article:publisher\" content=\"https://www.facebook.com/NSHipster\">\n  {% else %}\n    <meta property=\"og:title\" content=\"{{ site.title }}\"/>\n    <meta property=\"og:url\" content=\"{{ site.url }}\"/>\n    <meta property=\"og:description\" content=\"{{ site.description | markdownify | strip_html | escape }}\" />\n  {% endif %}\n\n  <link rel=\"canonical\" href=\"{{ page.url | absolute_url }}\" />\n\n  {% for translation in page.translations %}\n    {% assign translation_url = site.domains[translation] %}\n    {% if translation_url %}\n        <link rel=\"alternate\" hreflang=\"{{ translation }}\" href=\"{{ page.url | prepend:translation_url }}\" />\n    {% endif %}\n  {% endfor %}\n\n  <link rel=\"alternate\" hreflang=\"x-default\" href=\"{{ page.url | prepend:'https://nshipster.com' }}\" />\n\n  {% if page.url == '/' %}\n    <link rel=\"prerender\" href=\"{{ site.posts.first.url | absolute_url }}\" />\n  {% endif %}\n\n  {% if page.next %}\n    <link rel=\"next\" href=\"{{ page.next.url | absolute_url }}\" />\n  {% endif %}\n\n  {% if page.previous %}\n    <link rel=\"prev\" href=\"{{ page.previous.url | absolute_url }}\" />\n  {% endif %}\n\n  {% if page.retired %}\n    <meta name=\"robots\" content=\"noindex,nofollow\" />\n  {% endif %}\n\n  {% if site.url == \"https://nsmutablehipster.com\" %}\n    <meta name=\"robots\" content=\"noindex,nofollow\" />\n  {% endif %}\n\n  <meta name=\"monetization\" content=\"$coil.xrptipbot.com/nshipster\" />\n</head>\n\n<body>\n\n  <div class=\"container\">\n    <header role=\"banner\">\n      <a id=\"logo\" href=\"/\" title=\"NSHipster\" aria-label=\"NSHipster\">\n        {% asset logo.svg @inline role=\"img\" aria-hidden=\"true\" %}\n      </a>\n\n      {% if page.url == \"/\" %}\n        <h2 class=\"tagline\">{{ site.description | markdownify | unwrap }}</h2>\n      {% endif %}\n    </header>\n\n    <main>\n      {{ content }}\n    </main>\n\n    <footer role=\"contentinfo\">\n      <section class=\"credits colophon\">\n        <p>\n          <i aria-hidden=\"true\" class=\"icon-cc\" title=\"Creative Commons\">&#x1F16D;</i>\n          <i aria-hidden=\"true\" class=\"icon-by\" title=\"Attribution\">&#x1F16F;</i>\n          <i aria-hidden=\"true\" class=\"icon-nc\" title=\"Non-Commercial\">&#x1F10F;</i>\n          {% t license %}\n        </p>\n      </section>\n    </footer>\n  </div>\n\n  {% asset application.js !type defer='defer' %}\n\n  {% if site.url == \"https://nsmutablehipster.com\" %}\n    {% asset nsmutablehipster.js !type defer=\"defer\" %}\n  {% endif %}\n\n  {% if page.id and site.lang == 'en-US' %}\n    {% include json-ld/article.html %}\n  {% endif %}\n\n  {% include json-ld/organization.html %}\n  {% include json-ld/website.html %}\n</body>\n</html>\n"
  },
  {
    "path": "_layouts/error.html",
    "content": "---\nlayout: default\n---\n\n<article role=\"article\">\n  <h1 class=\"title\">NSError</h1>\n\n  <div class=\"content\">\n    {{ content }}\n  </div>\n</article>\n"
  },
  {
    "path": "_layouts/page.html",
    "content": "---\nlayout: default\n---\n\n<article role=\"article\">\n  <header role=\"heading\">\n    <h1 class=\"title\">\n      <a href=\"{{ page.url }}\">{{ page.title | escape | camel_break }}</a>\n    </h1>\n  </header>\n\n  <div class=\"content\">\n    {{ content }}\n  </div>\n</article>\n"
  },
  {
    "path": "_layouts/post.html",
    "content": "---\nlayout: default\n---\n\n{% assign author = site.authors | where:\"name\", page.author | first %}\n{% assign translator = site.translators | where: \"name\", page.translator | first %}\n{% capture date_format %}{% t format.date %}{% endcapture %}\n\n<article role=\"article\">\n  <header role=\"heading\">\n    <h1 class=\"title\">\n      <a href=\"{{ page.url }}\">{{ page.title | strip_html | escape | camel_break }}</a>\n    </h1>\n\n    <div class=\"byline\">\n    {% if page.authors %}\n        {% t written_by %}\n        <span class=\"authors\">\n        {% for auth in page.authors %}\n          {% if forloop.last %}&amp;{% endif %}\n          {% assign author = site.authors | where:\"name\",auth | first %}\n          <a rel=\"author\" class=\"author\" href=\"{{ author.url }}\">{{ author.name }}</a>\n        {% endfor %}\n        </span>\n        <wbr/>\n    {% elsif author %}\n      {% t written_by %}\n      <span class=\"authors\">\n        <a class=\"author\" href=\"{{ author.url }}\">{{ author.name }}</a>\n      </span>\n    {% elsif page.author %}\n        {% t written_by %}\n        <span class=\"authors\">\n            {{ page.translator }}\n        </span>\n    {% endif %}\n\n    {% if page.translators %}\n      {% t translated_by %}\n      <span class=\"translators\">\n      {% for trans in page.translators %}\n          {% if forloop.last %}&amp;{% endif %}\n          {% assign translator = site.translators | where:\"name\",trans | first %}\n          {% if translator %}\n            <a class=\"translator\" href=\"{{ translator.url }}\">{{ translator.name }}</a>\n          {% else %}\n            {{ trans }}\n          {% endif %}\n      {% endfor %}\n      </span>\n    {% elsif translator %}\n        {% t translated_by %}\n        <span class=\"translators\">\n          <a class=\"translator\" href=\"{{ translator.url }}\">{{ translator.name }}</a>\n        </span>\n    {% elsif page.translator %}\n        {% t translated_by %}\n        <span class=\"translators\">\n          {{ page.translator }}\n        </span>\n    {% endif %}\n\n    {% if page.last_revised_on %}\n        <time datetime=\"{{ page.last_revised_on | date_to_xmlschema }}\">{{ page.last_revised_on | date: date_format }}</time>\n    {% else %}\n        <time datetime=\"{{ page.date | date_to_xmlschema }}\">{{ page.date | date: date_format }}</time>\n    {% endif %}\n\n    {% if page.revisions %}\n        {% if page.commit_history_url %}\n            (<a href=\"{{ page.commit_history_url | uri_escape }}\" rel=\"noopener noreferrer\">{% t revised %}</a>)\n        {% else %}\n            ({% t revised %})\n        {% endif %}\n    {% endif %}\n    </div>\n  </header>\n\n  <div class=\"content\">\n    {{ content }}\n  </div>\n\n  <footer role=\"complementary\">\n    {% if site.lang == \"en-US\" %}\n        {% if page.revisions or page.status %}\n        <section id=\"revisions\">\n        <small>NSMutableHipster</small>\n\n        <p>\n        Questions? Corrections? <a href=\"https://github.com/NSHipster/articles/issues\">Issues</a> and <a href=\"https://github.com/NSHipster/articles/blob/master/{{ page.path | remove_first:'_posts/' }}\">pull requests</a> are always welcome.\n        </p>\n\n        <p class=\"status\">\n        {% if page.status.swift and page.status.swift != \"t.b.c.\" and page.status.swift != \"n/a\" %}\n            {% if page.status.reviewed %}\n                <em>This article uses Swift version {{ page.status.swift }} and was last reviewed on {{ page.status.reviewed }}.</em>\n            {% else %}\n                <em>This article uses Swift version {{ page.status.swift }}.</em>\n            {% endif %}\n\n            Find status information for all articles on the <a href=\"/status/\">status page</a>.\n        {% elsif page.status.reviewed %}\n            <em>This article was last reviewed on {{ page.status.reviewed }}.</em>\n        {% endif %}\n        </p>\n        </section>\n        {% endif %}\n    {% endif %}\n\n    <section id=\"attribution\">\n      {% include contributor.html role=\"author\" %}\n      {% if page.translator or page.translators %}\n        {% include contributor.html role=\"translator\" %}\n      {% endif %}\n    </section>\n\n    <section>\n      {% assign next_post = page.next %}\n      {% if next_post == nil or next_post.url == page.url or next_post.retired %}\n        {% assign next_post = site.posts | first %}\n      {% endif %}\n\n      {% if next_post and next_post.url != page.url %}\n      <div id=\"continue\">\n        <small>{% t next_article %}</small>\n        <article>\n          <h1 class=\"title\">\n            <a rel=\"next\" href=\"{{ next_post.url }}\">{{ next_post.title | strip_html | escape | camel_break }}</a>\n          </h1>\n\n          {{ next_post.excerpt | markdownify }}\n        </article>\n      </div>\n      {% endif %}\n    </section>\n  </footer>\n</article>\n\n{% include json-ld/breadcrumblist.html %}\n"
  },
  {
    "path": "_layouts/translator.html",
    "content": "---\nlayout: default\n---\n\n{% assign translator = page %}\n{% capture date_format %}{% t format.date %}{% endcapture %}\n\n<article class=\"author\">\n  <header role=\"heading\">\n    {% if translator.image %}\n      <img class=\"avatar\" alt=\"{{ translator.name }}\" src=\"{% asset \"{{ translator.image }}\" @path %}\" draggable=\"false\"/>\n    {% elsif translator.gravatar %}\n      <img class=\"avatar\" src=\"//0.gravatar.com/avatar/{{ translator.gravatar }}?size=300\" draggable=\"false\"/>\n    {% endif %}\n    <h1>{{ translator.name }}</h1>\n\n    {{ translator.content | markdownify }}\n  </header>\n\n  <section class=\"archive\">\n    <h1>{% t articles %}</h1>\n\n    <ol>\n    {% for post in site.posts %}\n      {% if post.translator == translator.name or post.translators contains translator.name %}\n        <li>\n          <a href=\"{{ post.url }}\" title=\"{{ post.title }}\" class=\"title\">{{ post.title }}</a>\n          <time datetime=\"{{ post.date | date_to_xmlschema }}\" >{{ post.date | date: date_format }}</time>\n\n          {{ post.excerpt | markdownify }}\n        </li>\n      {% endif %}\n    {% endfor %}\n    </ol>\n  </section>\n</article>\n\n"
  },
  {
    "path": "_plugins/admonition-block.rb",
    "content": "# frozen_string_literal: true\n\nmodule Jekyll\n  class AdmonitionBlock < Liquid::Block\n    def initialize(tag_name, arguments, tokens)\n      super\n\n      @type = tag_name\n    end\n\n    def render(context)\n      content = super\n      <<~EOD\n        <aside class=\"admonition #{@type}\" markdown=\"1\">\n         #{content}\n        </aside>\n      EOD\n    end\n  end\nend\n\n%w[info warning error].each do |admonition|\n  Liquid::Template.register_tag(admonition, Jekyll::AdmonitionBlock)\nend\n"
  },
  {
    "path": "_plugins/camel-case-thin-space-break-filter.rb",
    "content": "# frozen_string_literal: true\n\nmodule Jekyll\n  module CamelCaseThinSpaceBreakFilter\n    REGEX = /(?:([a-z]{2,})([A-Z]+))/.freeze\n\n    def camel_break(string)\n      string.gsub(REGEX, \"\\\\1\\u200B\\\\2\")\n            .gsub(/(mac|tv)\\u200B(OS)/, \"\\\\1\\\\2\")\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::CamelCaseThinSpaceBreakFilter)\n"
  },
  {
    "path": "_plugins/extended-date-filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'time'\n\nmodule Jekyll\n  module ExtendedDateFilter\n    # Reformat a date using Ruby's core Time#strftime( string ) -> string\n    # with additional replacements.\n    #\n    #   %a - The abbreviated weekday name (``Sun'')\n    #   %A - The full weekday name (``Sunday'')\n    #   %b - The abbreviated month name (``Jan'')\n    #   %B - The full month name (``January'')\n    #   %c - The preferred local date and time representation\n    #   %d - Day of the month (01..31)\n    #   %H - Hour of the day, 24-hour clock (00..23)\n    #   %I - Hour of the day, 12-hour clock (01..12)\n    #   %j - Day of the year (001..366)\n    #   %m - Month of the year (01..12)\n    #   %M - Minute of the hour (00..59)\n    #   %o - Ordinal for the day of the month (st, nd, rd, th...)\n    #   %p - Meridian indicator (``AM'' or ``PM'')\n    #   %s - Number of seconds since 1970-01-01 00:00:00 UTC.\n    #   %S - Second of the minute (00..60)\n    #   %U - Week number of the current year,\n    #           starting with the first Sunday as the first\n    #           day of the first week (00..53)\n    #   %W - Week number of the current year,\n    #           starting with the first Monday as the first\n    #           day of the first week (00..53)\n    #   %w - Day of the week (Sunday is 0, 0..6)\n    #   %x - Preferred representation for the date alone, no time\n    #   %X - Preferred representation for the time alone, no date\n    #   %y - Year without a century (00..99)\n    #   %Y - Year with century\n    #   %Z - Time zone name\n    #   %% - Literal ``%'' character\n    #\n    #   See also: http://www.ruby-doc.org/core/Time.html#method-i-strftime\n    def date(input, format)\n      return input unless date = datetime(input)\n      return input unless (format = format.to_s) && !format.empty?\n\n      date.strftime(format.gsub(/%o/, ordinal(date.day)))\n    end\n\n    private\n\n    def ordinal(number)\n      return 'th' if (11..13).cover?(number.to_i % 100)\n\n      case number.to_i % 10\n      when 1 then 'st'\n      when 2 then 'nd'\n      when 3 then 'rd'\n      else        'th'\n      end\n    end\n\n    def datetime(date)\n      case date\n      when String\n        Time.parse(date)\n      else\n        date\n      end\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::ExtendedDateFilter)\n"
  },
  {
    "path": "_plugins/jwt-lexer.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rouge'\n\nmodule Rouge\n  module Lexers\n    class JWT < RegexLexer\n      tag 'jwt'\n      filenames '*.jwt'\n\n      title 'JSON Web Token (JWT)'\n      desc 'A compact URL-safe means of representing claims to be transferred between two parties.'\n\n      start { push :root }\n\n      state :root do\n        rule %r{^([A-Za-z0-9\\-_=]+)(\\.)([A-Za-z0-9\\-_=]+)(\\.?)([A-Za-z0-9\\-_.+/=]*)$} do |m|\n          token Keyword, m[1]\n          token Punctuation, m[2]\n          token Literal::Number, m[1]\n          token Punctuation, m[4]\n          token Name::Variable, m[1]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "_plugins/localization-filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'twitter_cldr'\n\nmodule Jekyll\n  module LocalizationFilter\n    def as_language_code(input, locale = nil)\n      return '中文' if input == 'zh-Hans' && locale == 'zh-Hans'\n\n      code = TwitterCldr.convert_locale(input)\n      TwitterCldr::Shared::Languages.from_code_for_locale(code, locale || :en)\n    end\n\n    def to_sentence(list)\n      formatter = TwitterCldr::Formatters::ListFormatter.new(current_locale.language)\n      formatter.format(list.map(&:strip).reject(&:empty?))\n    end\n\n    private\n\n    def current_locale\n      # TwitterCldr.convert_locale(Jekyll.sites.first.config['lang'])\n      TwitterCldr::Shared::Locale.parse(Jekyll.sites.first.config['lang']).maximize\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::LocalizationFilter)\n"
  },
  {
    "path": "_plugins/markdown-converter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'yaml'\n\nrequire 'jekyll'\nrequire 'nokogiri'\nrequire 'active_support/inflector'\n\nmodule Jekyll\n  module Converters\n    class Markdown\n      # :nodoc:\n      class NSHipsterProcessor\n        def initialize(config)\n          @kramdown = KramdownParser.new(config)\n        end\n\n        def convert(content)\n          cache.getset(content) do\n            content.gsub!('<#...#>', \"\\uFFFC\")\n            html = @kramdown.convert(content)\n            doc = Nokogiri::HTML::DocumentFragment.parse(html)\n\n            remove_proprietary_attributes!(doc)\n            secure_links_to_cross_origin_destinations!(doc)\n            transform_apple_trademarks!(doc)\n            transform_code_symbols!(doc)\n            transform_placeholder_tokens!(doc)\n            add_heading_anchors!(doc)\n            unnest_code_listing_markup!(doc)\n            consolidate_consecutive_code_listings!(doc)\n            improve_accessibility!(doc)\n            style_optional_placeholders!(doc)\n            delineate_flim_flam!(doc)\n\n            doc.to_html.gsub(\"\\uFFFC\", '<var class=\"placeholder\">…</var>')\n          end\n        end\n\n        private\n\n        def cache\n          @@cache ||= Jekyll::Cache.new('ConvertMarkdown')\n        end\n\n        def remove_proprietary_attributes!(doc)\n          doc.css('[markdown]').each do |element|\n            element.remove_attribute('markdown')\n          end\n        end\n\n        def transform_code_symbols!(doc)\n          doc.css(':not(pre) code').each do |code|\n            code.remove_attribute('class')\n            code.inner_html = code.inner_html.gsub(/(?:([a-z])([A-Z]+))/, '\\\\1<wbr/>\\\\2')\n          end\n        end\n\n        def transform_apple_trademarks!(doc)\n          doc.css('p, li, td').each do |p|\n            p.inner_html = p.inner_html.gsub(/iPhone X([SR])/, 'iPhone X<small>\\\\1</small>')\n          end\n        end\n\n        def secure_links_to_cross_origin_destinations!(doc)\n          doc.css('a[href]').each do |a|\n            href = a.attr('href')\n            next if href =~ %r{^/|#{ENV['DOMAIN']}}\n\n            a['rel'] = 'noopener noreferrer'\n          end\n        end\n\n        def transform_placeholder_tokens!(doc)\n          doc.css('code').each do |code|\n            code.inner_html = code.inner_html.gsub(/&lt;#\\s*(.*?)\\s*#&gt;/, '<var class=\"placeholder\">\\\\1</var>')\n          end\n        end\n\n        def add_heading_anchors!(doc)\n          selector = (1..6).map { |n| \"h#{n}\" }.join(', ')\n          doc.css(selector).each do |h|\n            next unless id = h.attr('id')\n\n            id = ActiveSupport::Inflector.parameterize(id)\n\n            h.remove_attribute('id')\n            h.prepend_child(%(<a class=\"anchor\" aria-hidden=\"true\" id=\"#{id}\" href=\"##{id}\"></a>))\n          end\n        end\n\n        def unnest_code_listing_markup!(doc)\n          doc.css('div.highlighter-rouge').each do |div|\n            class_name = div.classes.detect { |c| !c.match?(/rouge/) }\n            language = case class_name\n                       when /swift/ then 'Swift'\n                       when /objc|objective-c/ then 'Objective-C'\n                       when /json-ld/ then 'JSON-LD'\n                       when /json/ then 'JSON'\n                       when /python/ then 'Python'\n                       when /ruby/ then 'Ruby'\n                       when /javascript/ then 'JavaScript'\n                       when /terminal/ then 'Terminal'\n                       when /html/ then 'HTML'\n                       when /xml/ then 'XML'\n                       when /jwt/ then 'JWT'\n                       when /applescript/ then 'AppleScript'\n                       when /lisp/ then 'Lisp'\n                       when /fortran/ then 'FORTRAN'\n                       when /cobol/ then 'COBOL'\n                       when /xcconfig/ then 'Xcode Build Settings'\n                       when /turtle/ then 'Turtle'\n                       when /sparql/ then 'SPARQL'\n                       when /sql/ then 'SQL'\n                       when /cypher/ then 'Cypher'\n                       when /ntriples/ then 'N-Triples'\n                       when nil then ''\n                       else\n                         class_name.gsub(/language-/, '')\n                       end\n\n            pre = div.at('pre')\n            pre['class'] = 'highlight'\n            pre['data-lang'] = language\n\n            div.swap(pre)\n          end\n        end\n\n        def consolidate_consecutive_code_listings!(doc)\n          doc.css('pre.highlight').each do |pre|\n            next if pre.parent['class'] == 'highlight-group'\n\n            group = pre.wrap(%(<div class=\"highlight-group\">)).parent\n\n            while sibling = group.at_xpath('following-sibling::node()[not(self::text()[not(normalize-space())])][1]')\n              break unless sibling.classes.include?('highlight')\n\n              group.add_child(sibling)\n            end\n\n            group.swap(group.child) if group.children.count == 1\n          end\n\n          number = 1\n          doc.css('div.highlight-group').each do |group|\n            group.prepend_child('<div role=\"tablist\" aria-label=\"Languages\"/>')\n            tablist = group.at('[role=\"tablist\"]')\n\n            group.css('pre.highlight').each_with_index do |div, index|\n              language = div['data-lang'] || 'text'\n\n              id = \"code-listing-#{number}-#{language.downcase}\"\n              div['id'] = id.to_s\n              div['role'] = 'tabpanel'\n              div['tabindex'] = '0'\n              div['aria-labelledby'] = \"#{id}-tab\"\n              div['hidden'] = 'hidden' unless index == 0\n\n              tablist.add_child(%(\n                  <button role=\"tab\"\n                          role=\"tablist\"\n                          id=\"#{id}-tab\"\n                          class=\"#{language.downcase}\"\n                          aria-label=\"Languages\"\n                          aria-controls=\"#{id}\"\n                          aria-selected=\"#{index == 0 ? 'true' : 'false'}\"\n                          tabindex=\"-1\">\n                      #{language}\n                  </button>\n              ))\n            end\n            number += 1\n          end\n        end\n\n        def improve_accessibility!(doc)\n          doc.css('img[src$=\".svg\"]').each do |img|\n            img['role'] = 'img'\n          end\n\n          doc.css('img:not([alt])').each do |img|\n            img['alt'] = ''\n          end\n        end\n\n        def style_optional_placeholders!(doc)\n          doc.css('var.placeholder').each do |var|\n            next unless var.text.match?(/[\\[\\]]/)\n\n            var.add_class('optional')\n            var['title'] = 'Optional'\n            var.inner_html = var.inner_html.gsub(/[\\[\\]]/, '')\n          end\n        end\n\n        def delineate_flim_flam!(doc)\n          if divider = (doc.at_css('hr') || doc.at_css('h2'))\n            divider.add_next_sibling(%(<a id=\"get-on-with-it\"/>))\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "_plugins/page-translation-hook.rb",
    "content": "# frozen_string_literal: true\n\nJekyll::Hooks.register :pages, :pre_render do |page|\n  page.data['translations'] = page.site.config['domains'].keys if page.index?\nend\n"
  },
  {
    "path": "_plugins/post-commit-history-hook.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'uri'\n\nJekyll::Hooks.register :posts, :pre_render do |post|\n  language = post.site.config['lang']\n\n  repository_name = case language\n                    when /^en/ then 'articles'\n                    when /^es/ then 'articles-es'\n                    when /^fr/ then 'articles-fr'\n                    when /^ko/ then 'articles-ko'\n                    when /^zh-Hans/ then 'articles-zh-Hans'\n                    when /^ru/ then 'articles-ru'\n                    when nil\n                      raise 'Unspecified language in site configuration'\n                    else\n                      raise \"Unknown language: #{language}\"\n                    end\n\n  filename = File.basename(post.path)\n\n  post.data['commit_history_url'] = \"https://github.com/nshipster/#{repository_name}/commits/master/#{filename}\"\nend\n"
  },
  {
    "path": "_plugins/post-revisions-hook.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'date'\n\nJekyll::Hooks.register :posts, :pre_render do |post|\n  if post.data['revisions']\n    latest_revision = post.data['revisions'].keys.max\n    raise unless latest_revision && (last_revised_on = Time.parse(\"#{latest_revision}\"))\n\n    post.data['revision_description'] = post.data['revisions'][latest_revision]\n    post.data['last_revised_on'] = last_revised_on\n    post.data['updated_on'] = last_revised_on\n  else\n    post.data['updated_on'] = post.date\n  end\nend\n"
  },
  {
    "path": "_plugins/post-translation-hook.rb",
    "content": "# frozen_string_literal: true\n\nJekyll::Hooks.register :posts, :pre_render do |post|\n  directory = File.expand_path('../../..', post.path)\n  filename = File.basename(post.path)\n  slug = filename.sub(/\\A\\d{4}-\\d{,2}-\\d{,2}-/, '')\n  translations = Dir[\"#{directory}/**/*#{slug}\"].reject { |f| f == post.path }\n\n  post.data['translations'] = []\n  translations.each do |translation|\n    next unless language = File.expand_path('../..', translation).split('/').last\n    post.data['translations'] << language\n  end\nend\n"
  },
  {
    "path": "_plugins/search-index-generator.rb",
    "content": "# frozen_string_literal: true\n\nmodule Jekyll\n  class SearchIndexGenerator < Generator\n    priority :low\n\n    def generate(site)\n      index = site.posts.docs.reverse\n                  .filter { |post| !post.data['retired'] }\n                  .map do |post|\n        {\n          url: site.config['url'] + post.url,\n          title: post.data['title'],\n          category: post.data['category'],\n          content: post.data['excerpt']\n        }\n      end\n\n      File.open('_functions/search/index.json', 'w') do |f|\n        f.puts index.to_json\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "_plugins/shuffle-filter.rb",
    "content": "# frozen_string_literal: true\n\nmodule Jekyll\n  module ShuffleFilter\n    def shuffle(input = [])\n      input.sort_by { rand }\n    rescue StandardError\n      input\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::ShuffleFilter)\n"
  },
  {
    "path": "_plugins/translate-tag.rb",
    "content": "# frozen_string_literal: true\n\nmodule Jekyll\n  class Site\n    attr_accessor :translations\n  end\n\n  class TranslateTag < Liquid::Tag\n    def initialize(tag_name, key, tokens)\n      super\n      @key = key.strip\n    end\n\n    def render(context)\n      key = key(context)\n      translation = translations(context).dig(*key.split('.'))\n\n      if translation.nil? || translation.empty?\n        raise \"Missing i18n key: #{lang}: #{key}\"\n      end\n\n      translation\n    end\n\n    private\n\n    def key(context)\n      key = if context[@key].to_s != ''\n              context[@key].to_s\n            else\n              @key\n            end\n\n      key = Liquid::Template.parse(key).render(context)\n      raise \"Invalid key #{key}\" unless key.is_a?(String)\n\n      key\n    end\n\n    def translations(context)\n      site = context.registers[:site]\n      site.translations ||= {}\n\n      lang = site.config['lang']\n      unless site.translations.key?(lang)\n        puts \"Loading translations from #{site.source}/_i18n/#{lang}.yml\"\n        site.translations[lang] = YAML.load_file(\"#{site.source}/_i18n/#{lang}.yml\")\n      end\n\n      site.translations[lang]\n    end\n  end\nend\n\nLiquid::Template.register_tag('t', Jekyll::TranslateTag)\nLiquid::Template.register_tag('translate', Jekyll::TranslateTag)\n"
  },
  {
    "path": "_plugins/unwrap-filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'nokogiri'\n\nmodule Jekyll\n  module UnwrapFilter\n    def unwrap(input)\n      return '' if input.nil? || input.empty?\n\n      fragment = Nokogiri::HTML::DocumentFragment.parse(input)\n      fragment.children.map(&:inner_html).join(' ')\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::UnwrapFilter)\n"
  },
  {
    "path": "_plugins/url-filter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'uri'\n\nmodule Jekyll\n  module URLFilter\n    def host(input)\n      return input unless uri = URI(input)\n\n      uri.host\n    end\n  end\nend\n\nLiquid::Template.register_filter(Jekyll::URLFilter)\n"
  },
  {
    "path": "_plugins/well-known-hook.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'fileutils'\n\nJekyll::Hooks.register :site, :post_write do |site|\n  site.static_files.select do |f|\n    next unless f.relative_path.include?('.well-known')\n\n    FileUtils.cp(f.path, site.dest)\n  end\nend\n"
  },
  {
    "path": "assets/css/_admonitions.scss",
    "content": "@mixin border-icon($name) {\n  content: \" \";\n  background-image: asset_url($name + \".svg\");\n  background-size: 24px 24px;\n  width: 24px;\n  height: 24px;\n  position: absolute;\n  display: block;\n  margin-left: -54px;\n  margin-top: 10px;\n  z-index: 100;\n}\n\n.admonition {\n  --code: var(--link);\n  font-family: $sans-serif-font-stack;\n  border-left: 4px var(--separator) solid;\n  padding: 5px 40px;\n  margin: 1.5em 0;\n  display: block;\n  clear: both;\n  overflow: visible;\n  font-size: smaller;\n\n  a {\n    text-decoration: underline;\n  }\n\n  p {\n    margin: 0.5em 0;\n  }\n\n  dl {\n    padding: 0.5em 0 !important;\n    margin-bottom: 1em !important;\n  }\n\n  pre code {\n    font-size: small;\n    line-height: 1;\n  }\n\n  th,\n  td {\n    padding: 0.5em !important;\n  }\n\n  blockquote {\n    margin-left: 0 !important;\n    margin-top: 0.25em !important;\n    margin-bottom: 0.25em !important;\n    border-left-color: var(--separator) !important;\n  }\n\n  ins {\n    background: transparent !important;\n  }\n\n  &.info {\n    --link: var(--blue);\n    --separator: var(--blue);\n    --background: #edf5fa;\n\n    &:before {\n      @include border-icon(\"info\");\n    }\n  }\n\n  &.warning {\n    --background: #fcfaf6;\n    --separator: var(--yellow);\n    --link: rgb(178, 129, 6);\n\n    &:before {\n      @include border-icon(\"warning\");\n    }\n  }\n\n  &.error {\n    --background: #fcf2f6;\n    --link: var(--pink);\n    --separator: var(--pink);\n\n    &:before {\n      @include border-icon(\"error\");\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/_animations.scss",
    "content": "@keyframes twirl {\n    0% {\n        transform: scale(1) rotate(0);\n    }\n\n    10%,\n    20% {\n        transform: scale(0.9) rotate(-3deg);\n    }\n\n    30%,\n    50%,\n    70%,\n    90% {\n        transform: scale(1.1) rotate(3deg);\n    }\n\n    40%,\n    60%,\n    80% {\n        transform: scale(1.1) rotate(-3deg);\n    }\n\n    100% {\n        transform: scale(1) rotate(0);\n    }\n}\n"
  },
  {
    "path": "assets/css/_code.scss",
    "content": "pre.highlight {\n  background: var(--secondary-background);\n  border: 1px var(--separator-opaque) solid;\n  border-radius: 4px;\n  overflow: auto;\n  padding: 0.5em 1em;\n  margin-bottom: 1em;\n\n  code {\n    color: var(--text);\n    background: transparent !important;\n  }\n\n  &[data-lang=\"JWT\"] {\n    white-space: pre-wrap;\n  }\n}\n\n.highlight {\n  .placeholder {\n    color: var(--text);\n  }\n\n  .o {\n    color: var(--text);\n  }\n\n  .p {\n    color: var(--gray);\n  }\n\n  .err {\n    color: var(--gray);\n  }\n\n  .s,\n  .sa,\n  .sb,\n  .sc,\n  .dl,\n  .sd,\n  .s2,\n  .sh,\n  .sx,\n  .sr,\n  .s1,\n  .ss {\n    color: var(--orange);\n  }\n\n  .se,\n  .si {\n    color: var(--text);\n  }\n\n  .k,\n  .kc,\n  .kd,\n  .kn,\n  .kp,\n  .kr {\n    color: var(--purple);\n  }\n\n  .kt {\n    color: var(--text);\n  }\n\n  .kd + .kt {\n    color: var(--text);\n  }\n\n  .go,\n  .nc,\n  .nf,\n  .nv {\n    color: var(--text);\n  }\n\n  .kt + .o + .n,\n  .nf {\n    color: var(--indigo);\n  }\n\n  .cp,\n  .c1 {\n    color: var(--gray);\n  }\n\n  .n,\n  .na,\n  .nb,\n  .bp,\n  .no,\n  .nd,\n  .ni,\n  .py,\n  .nl,\n  .nn,\n  .nx,\n  .nt,\n  .vc,\n  .vg,\n  .vi {\n    color: var(--text);\n  }\n\n  .l,\n  .ld,\n  .s,\n  .sb,\n  .sc,\n  .sd,\n  .s2,\n  .se,\n  .sh,\n  .si,\n  .sx,\n  .sr,\n  .s1,\n  .ss,\n  .m,\n  .mf,\n  .mh,\n  .mi,\n  .il,\n  .mo,\n  .mx,\n  .mb {\n    color: var(--indigo);\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  .highlight {\n    .p {\n      color: var(--gray2);\n    }\n\n    .err {\n      color: var(--gray);\n    }\n\n    .s,\n    .sa,\n    .sb,\n    .sc,\n    .dl,\n    .sd,\n    .s2,\n    .sh,\n    .sx,\n    .sr,\n    .s1,\n    .ss {\n      color: var(--green);\n    }\n\n    .se,\n    .si {\n      color: var(--text);\n    }\n\n    .k,\n    .kc,\n    .kd,\n    .kn,\n    .kp,\n    .kr {\n      color: var(--teal);\n    }\n\n    .kt {\n      color: var(--yellow);\n    }\n\n    .kd + .kt {\n      color: var(--orange);\n    }\n\n    .go,\n    .nc,\n    .nf,\n    .nv {\n      color: var(--text);\n    }\n\n    .kt + .o + .n,\n    .nf {\n      color: var(--purple);\n    }\n\n    .cp {\n      color: var(--red);\n    }\n\n    .c1 {\n      color: var(--gray2);\n    }\n\n    .n + .o + .n,\n    .na,\n    .nb,\n    .bp,\n    .no,\n    .nd,\n    .ni,\n    .py,\n    .nl,\n    .nn,\n    .nx,\n    .nt,\n    .vc,\n    .vg,\n    .vi {\n      color: var(--pink);\n    }\n\n    .l,\n    .ld,\n    .s,\n    .sb,\n    .sc,\n    .sd,\n    .s2,\n    .se,\n    .sh,\n    .si,\n    .sx,\n    .sr,\n    .s1,\n    .ss,\n    .m,\n    .mf,\n    .mh,\n    .mi,\n    .il,\n    .mo,\n    .mx,\n    .mb {\n      color: var(--orange);\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/_colors.scss",
    "content": ":root {\n  --red: rgb(255, 59, 48);\n  --orange: rgb(255, 128, 0);\n  --yellow: rgb(255, 204, 0);\n  --green: rgb(52, 199, 89);\n  --teal: rgb(90, 200, 250);\n  --blue: rgb(0, 122, 255);\n  --indigo: rgb(88, 86, 214);\n  --purple: rgb(175, 82, 222);\n  --pink: rgb(255, 45, 85);\n  --gray: rgb(142, 142, 147);\n  --gray2: rgb(174, 174, 178);\n  --gray3: rgb(199, 199, 204);\n  --gray4: rgb(209, 209, 214);\n  --gray5: rgb(229, 229, 234);\n  --gray6: rgb(242, 242, 247);\n\n  --text: rgb(0, 0, 0);\n  --secondary-text: rgb(60, 60, 67);\n  --placeholder-text: rgb(60, 60, 67);\n  --code: var(--purple);\n  --link: var(--orange);\n  --separator: rgb(60, 60, 67);\n  --opaque-separator: rgb(198, 198, 200);\n  --fill: rgb(120, 120, 128);\n  --secondary-fill: rgb(120, 120, 128);\n  --background: rgb(242, 242, 247);\n  --secondary-background: rgb(255, 255, 255);\n}\n\n@supports (color: color(display-p3 1 1 1)) {\n  * {\n    transition: none !important;\n  }\n\n  :root {\n    --red: color(display-p3 1 0.2314 0.1882);\n    --orange: color(display-p3 1 0.5 0);\n    --yellow: color(display-p3 1 0.8 0);\n    --green: color(display-p3 0.2039 0.7804 0.349);\n    --teal: color(display-p3 0.3529 0.7843 0.9804);\n    --blue: color(display-p3 0 0.4784 1);\n    --indigo: color(display-p3 0.3451 0.3373 0.8392);\n    --purple: color(display-p3 0.6863 0.3216 0.8706);\n    --pink: color(display-p3 1 0.1765 0.3333);\n    --gray: color(display-p3 0.5569 0.5569 0.5765);\n    --gray2: color(display-p3 0.6824 0.6824 0.698);\n    --gray3: color(display-p3 0.7804 0.7804 0.8);\n    --gray4: color(display-p3 0.8196 0.8196 0.8392);\n    --gray5: color(display-p3 0.898 0.898 0.9176);\n    --gray6: color(display-p3 0.949 0.949 0.9686);\n\n    --text: color(display-p3 0 0 0);\n    --secondary-text: color(display-p3 0.2353 0.2353 0.2627);\n    --placeholder-text: color(display-p3 0.2353 0.2353 0.2627);\n    --separator: color(display-p3 0.2353 0.2353 0.2627);\n    --opaque-separator: color(display-p3 0.7765 0.7765 0.7843);\n    --fill: color(display-p3 0.4706 0.4706 0.502);\n    --secondary-fill: color(display-p3 0.4706 0.4706 0.502);\n    --background: color(display-p3 0.949 0.949 0.9686);\n    --secondary-background: color(display-p3 1 1 1);\n  }\n}\n\nhtml {\n  border-top: 3px var(--orange) solid;\n\n  body {\n    background-color: var(--background);\n    color: var(--text);\n  }\n}\n\n#logo {\n  #ns {\n    fill: var(--orange);\n  }\n}\n"
  },
  {
    "path": "assets/css/_functions.scss",
    "content": "@mixin clearfix {\n  &:after {\n    content: \" \";\n    display: block;\n    clear: both;\n  }\n}\n\n@mixin disable-selection {\n  -webkit-touch-callout: none; /* iOS Safari */\n  -webkit-user-select: none; /* Safari */\n  -khtml-user-select: none; /* Konqueror HTML */\n  -moz-user-select: none; /* Firefox */\n  -ms-user-select: none; /* Internet Explorer/Edge */\n  user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */\n}\n"
  },
  {
    "path": "assets/css/_inputs.scss",
    "content": "button,\ninput[type=\"submit\"] {\n  -moz-appearance: none;\n  -ms-appearance: none;\n  -o-appearance: none;\n  -webkit-appearance: none;\n  -webkit-font-smoothing: antialiased;\n  appearance: none;\n  background-color: var(--orange);\n  border-radius: 4px;\n  border: none;\n  color: white;\n  cursor: pointer;\n  display: inline-block;\n  font-size: 1em;\n  font-weight: bold;\n  line-height: 1;\n  padding: 0.75em 1em;\n  text-decoration: none;\n  transition: background-color 0.25s;\n  user-select: none;\n  vertical-align: middle;\n  white-space: nowrap;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover {\n  color: white;\n}\n"
  },
  {
    "path": "assets/css/_layout.scss",
    "content": "@import \"functions\";\n\nhtml,\nbody {\n  margin: 0;\n}\n\nbody {\n  padding: env(safe-area-inset-top) env(safe-area-inset-right)\n    env(safe-area-inset-bottom) env(safe-area-inset-left);\n  border-top: 3px var(--orange) solid;\n}\n\nhr {\n  border: none;\n  margin: 1em 0;\n  padding: 1em 0;\n  display: block;\n}\n\nimg {\n  margin: 0;\n  max-width: 100%;\n}\n\nvideo {\n  margin: 0 auto;\n  max-width: 100%;\n  display: block;\n}\n\nblockquote {\n  border-left: 2px solid var(--separator);\n  color: var(--secondary-text);\n  margin: 1.5em 0;\n  padding-left: 0.75em;\n}\n\ncite {\n  color: var(--text);\n  font-style: italic;\n\n  &:before {\n    content: \"— \";\n  }\n}\n\ntable {\n  border-collapse: collapse;\n  margin: 0.75em 0;\n  table-layout: fixed;\n  width: 100%;\n}\n\nthead th {\n  border-bottom: 1px solid var(--separator-opaque);\n  font-weight: bold;\n  padding: 0.75em 0;\n  text-align: left;\n}\n\ntbody td {\n  border-bottom: 1px solid var(--separator);\n  padding: 0.75em 0;\n}\n\ntbody tr:last-of-type td {\n  border-bottom: none;\n}\n\ntr,\ntd,\nth {\n  vertical-align: middle;\n}\n\nul,\nol {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n\ndl {\n  margin-bottom: 0.75em;\n\n  dt {\n    font-weight: bold;\n    margin: 1em 0;\n  }\n\n  dd {\n    margin: 0 0 0.25rem 1em;\n  }\n}\n\n.container {\n  @include clearfix;\n\n  max-width: 100%;\n  margin-left: auto;\n  margin-right: auto;\n  max-width: 960px;\n  margin: 0 auto;\n  padding: 2em;\n\n  section {\n    @include clearfix;\n\n    display: block;\n    max-width: 100%;\n    margin-left: auto;\n    margin-right: auto;\n    margin-bottom: 2em;\n    padding-bottom: 1em;\n  }\n}\n\nhtml[lang=\"fr-FR\"] [role=\"banner\"] {\n  #logo {\n    margin-right: 5.5em;\n  }\n\n  .tagline {\n    font-size: 1.25em;\n  }\n}\n\nhtml[lang=\"zh-Hans\"] [role=\"banner\"] {\n  #logo {\n    margin-right: 9.5em;\n  }\n\n  .tagline {\n    font-size: 1.4em;\n    padding-bottom: 1em;\n  }\n}\n\nhtml[lang=\"ko-KR\"] [role=\"banner\"] {\n  .tagline {\n    font-size: 1.25em;\n  }\n}\n\n[role=\"banner\"] {\n  display: flex;\n  margin-bottom: 1.5em;\n  padding-bottom: 1.5em;\n\n  #logo {\n    display: block;\n    -webkit-touch-callout: none;\n    -webkit-user-select: none;\n    -khtml-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n    font-size: 1em;\n    height: 6em;\n    margin: 0.25em 6em 0 0;\n\n    a {\n      display: block;\n    }\n\n    svg {\n      width: 146px;\n      height: 84px;\n      overflow: visible;\n      margin-left: -3px;\n\n      #mustache {\n        position: absolute;\n        transform: rotate(0) scale(1);\n        transform-origin: 50% 70% 0;\n        transition: transform 1s;\n      }\n\n      &:hover,\n      &.animated {\n        position: relative;\n        z-index: 2;\n\n        #mustache {\n          animation: twirl 1s ease-in-out;\n        }\n      }\n    }\n  }\n\n  .tagline {\n    flex: 1;\n  }\n}\n\n#latest,\n#announcement {\n  h1 {\n    margin-bottom: 0.5rem;\n  }\n}\n\n#announcement {\n  background-color: rgba(255, 128, 0, 0.2);\n  margin-left: -1em;\n  margin-right: -1em;\n  padding: 1em;\n}\n\n#recent {\n  ul {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 1em 2em;\n\n    li {\n      min-height: 15em;\n\n      .title {\n        height: 4em;\n        font-size: 1.75em;\n        display: table-cell;\n        line-height: 1;\n        vertical-align: bottom;\n        padding-bottom: 1em;\n      }\n\n      p {\n        font-size: smaller;\n        display: -webkit-box;\n        overflow: hidden;\n        max-lines: 8;\n        -webkit-line-clamp: 8;\n        -webkit-box-orient: vertical;\n        text-overflow: ellipsis;\n      }\n    }\n  }\n}\n\n#merchandise {\n  margin-top: -30px;\n\n  h1 {\n    margin-bottom: 15px;\n  }\n}\n\narticle.author,\narticle.translator {\n  padding-top: 2em;\n\n  header {\n    display: grid;\n    grid-template:\n      \"avatar . title\"\n      \"avatar . description\";\n    grid-template-columns: 1fr 1em 3fr;\n    grid-template-rows: 1fr 2fr;\n    gap: 1em 1em;\n    margin-bottom: 1em;\n    padding-bottom: 1em;\n\n    .avatar {\n      grid-area: avatar;\n    }\n\n    h1 {\n      grid-area: title;\n    }\n\n    p {\n      grid-area: description;\n    }\n  }\n}\n\n[role=\"article\"] {\n  margin-bottom: 1em;\n  overflow-x: hidden;\n\n  table {\n    overflow: scroll;\n    -webkit-overflow-scrolling: touch;\n    margin: 2em 0;\n\n    caption {\n      margin: 2em 0 1em 0;\n    }\n  }\n\n  header {\n    display: block;\n    text-align: center;\n    margin-bottom: 3em;\n\n    .byline {\n      font-family: $serif-font-stack;\n      font-style: italic;\n      font-weight: 300;\n      color: var(--secondary-text);\n\n      a,\n      span,\n      time {\n        white-space: nowrap;\n      }\n\n      .authors,\n      .translators {\n        &:after {\n          content: \" — \";\n        }\n      }\n    }\n  }\n\n  .content {\n    margin-bottom: 4em;\n\n    h1,\n    h2,\n    h3,\n    h4,\n    h5 {\n      margin-top: 2.5rem;\n    }\n\n    object,\n    embed,\n    figure,\n    svg {\n      margin: 1em auto;\n      display: block;\n      width: auto;\n    }\n\n    img {\n      margin: 1em auto;\n      display: block;\n    }\n\n    ul,\n    ol {\n      margin: 1.5em 0;\n      padding: 0 3em;\n\n      ul,\n      ol {\n        margin-top: 0.5em;\n      }\n\n      li {\n        list-style: disc;\n      }\n    }\n\n    figure {\n      text-align: center;\n      margin: 1em 0;\n      padding: 1em 0;\n    }\n\n    ins {\n      background-color: rgba(255, 128, 0, 0.2);\n      text-decoration: none;\n    }\n\n    dl {\n      padding: 1em 0;\n    }\n\n    blockquote {\n      margin: 2em;\n      margin-right: 4em;\n      border-left: 3px var(--orange) solid;\n\n      cite {\n        margin-top: 1em;\n        display: block;\n      }\n    }\n\n    table {\n      thead th {\n        text-align: center;\n      }\n\n      td {\n        padding: 1em;\n      }\n\n      table {\n        margin: 0;\n        th,\n        td {\n          border: none;\n          padding: 0.25em;\n        }\n      }\n    }\n  }\n\n  sup {\n    font-size: 50%;\n\n    time & {\n      margin-right: -0.5em;\n    }\n  }\n\n  footer {\n    .contributor {\n      float: left;\n      display: block;\n      margin-right: 2.35765%;\n      width: 48.82117%;\n      padding: 1em 0;\n\n      &:last-child,\n      &:nth-child(2n) {\n        margin-right: 0;\n      }\n\n      &:nth-child(2n + 1) {\n        clear: left;\n      }\n\n      &:only-child {\n        width: 100%;\n\n        .avatar {\n          padding: 0 1em;\n        }\n      }\n\n      .avatar {\n        float: left;\n        display: block;\n        margin-right: 4.82916%;\n        width: 30.11389%;\n\n        &:last-child {\n          margin-right: 0;\n        }\n      }\n\n      .details {\n        float: left;\n        display: block;\n        margin-right: 4.82916%;\n        width: 65.05695%;\n        margin-right: 0;\n        margin-top: 1em;\n\n        &:last-child {\n          margin-right: 0;\n        }\n\n        span {\n          font-weight: 700;\n        }\n\n        p {\n          font-size: 0.75em;\n          margin-top: 1em;\n        }\n      }\n    }\n\n    small {\n      display: block;\n      font-size: 1em;\n      font-weight: 700;\n      color: var(--secondary-text);\n      text-transform: lowercase;\n      font-family: $sans-serif-font-stack;\n      font-variant: small-caps;\n      margin-bottom: 1em;\n    }\n  }\n}\n\n[role=\"complementary\"] {\n  border-top: 1px #ddd solid;\n  padding-top: 2em;\n}\n\n[role=\"contentinfo\"] {\n  text-align: center;\n  margin-top: 2em;\n  padding: 1em;\n\n  section {\n    margin-bottom: 0;\n    padding-bottom: 0;\n  }\n}\n\n.avatar {\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  max-width: 200px;\n  max-height: 200px;\n  border-radius: 50%;\n  pointer-events: none;\n  user-select: none;\n}\n\n#contributors {\n  ul {\n    display: flex;\n    justify-content: center;\n    align-content: space-between;\n    flex-flow: row wrap;\n\n    li {\n      flex: 0;\n      display: block;\n      margin-bottom: 1em;\n      flex-basis: 15%;\n      padding: 0.25em;\n\n      .avatar {\n        width: 75%;\n        display: block;\n        margin: 0 auto 1em auto;\n      }\n\n      a {\n        text-align: center;\n        display: block;\n        font-size: small;\n      }\n    }\n  }\n}\n\n.archive {\n  dl {\n    float: left;\n    display: block;\n    margin-right: 2.5%;\n    width: 30%;\n\n    &:last-child,\n    &:nth-of-type(3),\n    &:nth-of-type(4),\n    &:nth-of-type(6) {\n      margin-right: 0;\n    }\n  }\n\n  ol,\n  ul {\n    list-style: none;\n\n    li {\n      margin: 2em 0;\n    }\n\n    span,\n    time {\n      display: block;\n    }\n\n    time {\n      white-space: nowrap;\n      font-style: italic;\n      font-weight: 300;\n      margin-bottom: 1em;\n    }\n  }\n}\n\n#publications {\n  .books {\n    display: flex;\n  }\n\n  .book {\n    flex: 1;\n\n    img {\n      display: block;\n      margin: 0 auto;\n      width: 200px;\n      border: 4px transparent solid;\n      transition: 0.25s ease-in-out border-color;\n      filter: none !important;\n\n      &:hover {\n        padding: 0;\n        border: 4px var(--orange) solid;\n      }\n    }\n  }\n}\n\n.tagline {\n  clear: both;\n  font-weight: 300;\n}\n\n.highlight-group {\n  margin-top: 1em;\n}\n\n[role=\"tablist\"] {\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-end;\n  padding-right: 3px;\n\n  button {\n    cursor: pointer;\n    flex: 0;\n    padding-left: 0.5em;\n    color: var(--fill) !important;\n    text-decoration: none;\n    transition: opacity 0.5s;\n    background: transparent !important;\n    padding: 0;\n    margin: 0 0 0 0.5em;\n\n    &:not([aria-selected=\"true\"]) {\n      opacity: 0.25;\n\n      &:hover {\n        opacity: 0.5;\n      }\n    }\n\n    &.active {\n      opacity: 1;\n    }\n\n    &:focus {\n      outline: thin dotted;\n      outline-offset: 2px;\n    }\n  }\n}\n\n[role=\"tabpanel\"] {\n  margin-top: 0.25em;\n\n  &:focus {\n    outline: 0;\n  }\n}\n\n#promotion {\n  article {\n    background-color: rgba(255, 128, 0, 0.2);\n    background-color: color(p3 1 0.5 0 0.2);\n    margin-left: -1em;\n    margin-right: -1em;\n    margin-top: 0.5em;\n    padding: 1.5em 1em;\n  }\n\n  .book {\n    @include disable-selection;\n    float: left;\n    width: 500px;\n    margin-left: -150px;\n    margin-top: -150px;\n    margin-right: -20px;\n\n    img {\n      margin: 0;\n      margin-top: 100px;\n    }\n  }\n\n  & > small {\n    font-style: italic;\n  }\n\n  h3 {\n    font-family: $serif-font-stack;\n    font-size: 1.25em;\n    margin-bottom: 0.5em;\n\n    a {\n      color: inherit;\n    }\n  }\n\n  h4 {\n    font-family: $serif-font-stack;\n    font-style: italic;\n    font-weight: 300;\n    margin-bottom: 1em;\n\n    sup {\n      vertical-align: baseline;\n      font-size: 1;\n    }\n  }\n\n  p {\n    font-size: 0.75em;\n  }\n\n  a.buy {\n    background: var(--orange);\n    border-radius: 10px;\n    color: white !important;\n    font-family: $sans-serif-font-stack;\n    font-weight: 700;\n    margin-top: 1em;\n    padding: 0.5em 1.5em;\n    text-align: center;\n    display: inline-block;\n\n    &:hover {\n      text-decoration: none !important;\n    }\n  }\n\n  .price {\n    cursor: help;\n    display: block;\n    text-align: right;\n    float: right;\n    padding-left: 1em;\n    * {\n      display: block;\n    }\n\n    del {\n      font-size: smaller;\n    }\n    ins {\n      text-decoration: none;\n      font-size: larger;\n    }\n  }\n}\n\ntable#status {\n  table-layout: fixed;\n  margin-top: 2em;\n\n  caption {\n    padding: 1em 0;\n    color: var(--secondary-text);\n  }\n\n  .version {\n    text-align: center;\n\n    em {\n      color: var(--secondary-text);\n    }\n  }\n}\n\ntable#customplaygrounddisplayconvertible-categories {\n  table-layout: auto;\n\n  tbody th {\n    padding-left: 10px;\n    text-align: center;\n  }\n\n  ul {\n    padding: 0 0 0 20px;\n\n    li {\n      margin: 0;\n    }\n  }\n\n  td img {\n    margin: 0;\n  }\n}\n\n@media screen and (max-width: 600px) {\n  table#customplaygrounddisplayconvertible-categories {\n    thead tr th:last-child,\n    tbody tr td:last-child {\n      display: none;\n    }\n  }\n}\n\ndetails {\n  summary {\n    cursor: pointer;\n    margin-bottom: 1em;\n    user-select: none;\n    -ms-user-select: none;\n    -moz-user-select: none;\n    -webkit-user-select: none;\n  }\n}\n\n#translations {\n  font-size: smaller;\n\n  dt,\n  dd {\n    font-weight: 300 !important;\n    display: inline;\n    margin: 0;\n    font-display: optional;\n    font-style: normal;\n  }\n}\n\n[hidden] {\n  display: none !important;\n}\n"
  },
  {
    "path": "assets/css/_typography.scss",
    "content": "@import \"fonts/merriweather\";\n@import \"fonts/batang\";\n@import \"fonts/cc\";\n@import \"colors\";\n\n$serif-font-stack: \"Merriweather\", Georgia, serif, \"Apple Color Emoji\",\n  \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n\n$sans-serif-font-stack: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n  Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\",\n  \"Segoe UI Symbol\";\n\n$mono-font-stack: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier,\n  monospace;\n\nhtml,\nbody {\n  font-family: $serif-font-stack;\n  font-size: 16pt;\n  line-height: 21pt;\n  font-weight: 300;\n  font-kerning: normal;\n  -webkit-font-kerning: normal;\n  -webkit-font-smoothing: antialiased;\n  text-rendering: optimizeLegibility;\n}\n\nhtml[lang=\"ko-KR\"] {\n  body {\n    font-family: \"Batang\", $serif-font-stack;\n    font-weight: lighter;\n  }\n}\n\nhtml[lang=\"ko-KR\"],\nhtml[lang=\"zh-Hans\"] {\n  a.readmore,\n  section > h1,\n  article p em,\n  article p dfn,\n  cite {\n    font-style: normal;\n    font-weight: bold;\n  }\n\n  [role=\"article\"] header .byline {\n    font-style: normal;\n  }\n\n  .archive {\n    ol li time,\n    ul li time {\n      font-style: normal;\n      font-weight: bold;\n    }\n  }\n\n  #promotion h4 {\n    font-style: normal;\n    font-weight: bold;\n  }\n\n  .highlight span {\n    font-style: normal !important;\n  }\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  font-family: $sans-serif-font-stack;\n  line-height: 1.1em;\n  margin: 0 0 1rem 0;\n\n  small {\n    display: block;\n    font-size: small;\n    font-variant: small-caps;\n    text-transform: uppercase;\n    font-weight: normal;\n    line-height: 2;\n    letter-spacing: 0.2ch;\n  }\n\n  em {\n    font-style: normal;\n  }\n}\n\nh1 {\n  font-size: 2.5em;\n}\n\nh2 {\n  font-size: 2em;\n}\n\nh3 {\n  font-size: 1.5em;\n}\n\nh4 {\n  font-size: 1.25em;\n}\n\nh5 {\n  font-size: 1.125em;\n}\n\nh6 {\n  font-size: 1em;\n}\n\np {\n  margin: 0 0 1rem 0;\n}\n\na {\n  transition: color 0.1s linear;\n  text-decoration: none;\n\n  &,\n  &:visited {\n    color: var(--link);\n  }\n\n  &:hover {\n    text-decoration: underline;\n  }\n\n  &:active,\n  &:focus {\n    outline: none;\n  }\n\n  code {\n    white-space: nowrap;\n    text-decoration: underline;\n  }\n}\n\np > small {\n  font-size: inherit;\n  font-variant: small-caps;\n  text-transform: lowercase;\n}\n\n:not(pre) > code {\n  user-select: all;\n}\n\n:matches(a, p, li, dd, td) {\n  code {\n    padding: 0.25em;\n    font-size: smaller;\n    border-radius: 4px;\n  }\n}\n\n:matches(p, li, dd, td) {\n  code {\n    color: var(--code);\n  }\n}\n\nol,\nul {\n  li {\n    margin-bottom: 0.5em;\n  }\n}\n\npre {\n  font-family: $serif-font-stack;\n}\n\ncode,\nsamp {\n  font-family: $mono-font-stack;\n}\n\npre code,\nsamp {\n  font-size: smaller;\n  line-height: 1.1em;\n}\n\nsamp {\n  white-space: pre;\n  overflow: scroll;\n  -webkit-overflow-scrolling: touch;\n  display: block;\n  padding: 0.5em 0;\n}\n\nsection > h1 {\n  font-family: $serif-font-stack;\n  font-weight: 300;\n  font-size: 1.5em;\n  text-align: center;\n  margin-bottom: 2rem;\n  margin-top: 2rem;\n}\n\narticle.excerpt h1 {\n  font-size: 1.5em;\n}\n\na.readmore {\n  font-style: italic;\n}\n\nkbd {\n  border-radius: 4px;\n  border: 1px var(--separator) solid;\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #fff inset;\n  font-family: $sans-serif-font-stack;\n  font-variant: small-caps;\n  margin: 0 0.1em;\n  padding: 0.1em 0.6em;\n  text-transform: lowercase;\n}\n\nabbr,\n.small-caps {\n  font-variant: small-caps;\n  text-transform: lowercase;\n}\n\n.placeholder {\n  color: var(--placeholder-text);\n  display: inline-block;\n  padding: 0.25em;\n  border: 1px var(--opaque-separator) solid;\n  border-radius: 4px;\n  font-style: normal;\n\n  &.optional {\n    opacity: 0.5;\n  }\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  &:hover .anchor::before {\n    opacity: 1;\n  }\n}\n\n.title {\n  font-family: $sans-serif-font-stack;\n  font-weight: 700;\n}\n\n.anchor::before {\n  content: \"#\";\n  opacity: 0;\n  transition: 300ms opacity;\n  position: absolute;\n  float: left;\n  margin-left: -1.5em;\n  padding: 0 0.5em;\n  color: var(--secondary-text) !important;\n  text-decoration: none;\n\n  :focus {\n    outline: none;\n  }\n}\n\n.tagline {\n  font-size: 1.33em;\n}\n\n#latest,\n#announcement {\n  small {\n    font-style: italic;\n  }\n}\n\n[role=\"article\"] {\n  header {\n    h1 {\n      font-size: 3.5em;\n      line-height: 1;\n      margin-bottom: 0.5rem;\n      padding: 0.5rem 0;\n    }\n  }\n}\n\n#archive {\n  dd {\n    font-size: smaller;\n    display: list-item;\n    list-style: circle;\n  }\n}\n\n.nowrap {\n  white-space: nowrap;\n}\n\n[lang*=\"-fonipa\"] {\n  font-family: $sans-serif-font-stack;\n  font-weight: normal;\n  font-style: normal;\n}\n\n[lang*=\"-Zsye\"] {\n  font-style: normal !important;\n}\n\nfigcaption {\n  font-style: italic;\n  font-size: smaller;\n}\n\ntable * {\n  font-feature-settings: \"tnum\";\n}\n\naside.parenthetical {\n  font-size: smaller;\n  font-style: italic;\n  color: var(--secondary-text);\n  padding-bottom: 1em;\n\n  p:before {\n    content: \"(\";\n  }\n\n  p:after {\n    content: \")\";\n  }\n\n  a,\n  code {\n    color: var(--secondary-text) !important;\n    background: transparent !important;\n  }\n\n  a {\n    text-decoration: underline;\n  }\n}\n\nli aside.parenthetical {\n  display: inline-block;\n  padding-bottom: 0;\n\n  p {\n    margin-bottom: 0;\n  }\n}\n\n.bibliography {\n  font-size: smaller;\n}\n\ndel {\n  opacity: 0.5;\n}\n\n[role=\"contentinfo\"] i {\n  font-family: \"Creative Commons Symbols\";\n  font-style: normal;\n}\n"
  },
  {
    "path": "assets/css/articles/1password-cli.scss",
    "content": "figure#create-vault-dialog {\n    display: block;\n    width: 360px !important;\n    border-radius: 10px;\n    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n    margin: 0 auto;\n    display: block;\n    padding: 10px;\n    background-color: #fff;\n    border: 1px solid #ccc;\n}\n\n@media (prefers-color-scheme: dark) {\n    figure#create-vault-dialog {\n        border-color: #777;\n        background-color: #262626;\n    }\n}\n\nspan.field {\n    font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n    border: 1px solid #0370eb;\n    padding: 0.1rem 0.2rem;\n    border-radius: 0.2rem;\n}\n\ndiv.fields {\n    margin-top: 0.5rem;\n    font-size: 0.8rem;\n}\n\nfigure#authorization-modal {\n    display: block;\n    width: 360px !important;\n    margin: 0 auto;\n}\n\n.highlight {\n    .gd {\n        background-color: rgba(255, 59, 48, 0.5);\n    }\n\n    .gi {\n        background-color: rgba(52, 199, 89, 0.5);\n    }\n}\n"
  },
  {
    "path": "assets/css/articles/as-we-may-code.scss",
    "content": ".nohighlight * {\n  color: var(--gray) !important;\n}\n\np > code {\n  .kd {\n    color: var(--teal);\n  }\n\n  .nf {\n    color: var(--purple);\n  }\n\n  .p {\n    color: var(--gray);\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/availability.scss",
    "content": "figure#wavailability {\n  table {\n    table-layout: auto;\n    font-size: smaller;\n\n    td[colspan=\"7\"] {\n      text-align: left;\n    }\n\n    table {\n      td {\n        padding: 0.5em;\n        border-bottom: 1px solid #b7b7b7;\n      }\n      tr:last-of-type td {\n        border: none;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/caemitterlayer.scss",
    "content": "#webgl-confetti {\n    position: relative;\n    width: 500px;\n    margin: 1em auto;\n    display: block;\n    canvas {\n        position: absolute;\n        z-index: 1000;\n    }\n}\n\nvideo {\n    width: 300px;\n}\n\ndl {\n    display: grid;\n    grid-template-columns: min-content auto;\n    gap: 0.5em 1em;\n  }\n\n  dt {\n    grid-column-start: 1;\n    margin: 0 !important;\n  }\n\n  dd {\n    grid-column-start: 2;\n    margin: 0 0 1em 0 !important;\n  }\n\n@media (prefers-reduced-motion: reduce) {\n    #webgl-confetti {\n        display: none !important;\n    }\n}\n"
  },
  {
    "path": "assets/css/articles/callable.scss",
    "content": "dl {\n  display: grid;\n  grid-template-columns: min-content auto;\n  gap: 0.5em 1em;\n}\n\ndt {\n  grid-column-start: 1;\n  margin: 0 !important;\n}\n\ndd {\n  grid-column-start: 2;\n  margin: 0 0 1em 0 !important;\n}\n"
  },
  {
    "path": "assets/css/articles/characterset.scss",
    "content": "@import \"colors\";\n@import \"functions\";\n\n.conversation {\n  @include clearfix;\n\n  margin: 1em auto;\n  max-width: 650px;\n\n  ruby {\n    ruby-align: start;\n    ruby-position: over;\n    display: block;\n    clear: both;\n    max-width: 550px;\n\n    &.boke {\n      float: left;\n      text-align: left;\n      margin-bottom: 0.5em;\n    }\n\n    &.tsukkomi {\n      float: right;\n      color: var(--orange);\n      text-align: right;\n      margin-bottom: 1.5em;\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/dark-mode.scss",
    "content": ".color {\n  background: var(--color);\n  display: inline-block;\n}\n\np .color {\n  width: 0.8em;\n  height: 0.8em;\n  border-radius: 0.2ch;\n}\n\ntable {\n  table-layout: auto;\n\n  thead {\n    tr:not(:first-of-type) th {\n      font-weight: normal;\n      font-size: 0.5em;\n    }\n  }\n\n  td {\n    padding: 0.5em 0 !important;\n  }\n\n  .color {\n    width: 64px;\n    height: 64px;\n    border-radius: 8px;\n    display: block;\n    margin: 0 auto;\n  }\n}\n\ntd.dark {\n  background: #2c2a28;\n}\n\n@media (prefers-color-scheme: dark) {\n  td.light {\n    background: #fefefe;\n  }\n}\n\n@media screen and (max-width: 768px) {\n  table td .color {\n    width: 32px;\n    height: 32px;\n    border-radius: 4px;\n  }\n}\n\n#fixed-colors {\n  display: grid;\n  grid-template-columns: 1fr 0 1fr;\n}\n\n@media screen and (min-width: 768px) {\n  #semantic-colors {\n    column-count: 2;\n    column-fill: balance;\n\n    dl {\n      margin-top: 0;\n      padding-top: 0;\n    }\n\n    dt {\n      margin-top: 2em;\n    }\n\n    dd {\n      break-before: avoid;\n      break-inside: avoid;\n      -webkit-column-break-before: avoid;\n      margin-bottom: 0.5em;\n      &:before {\n        content: \"• \";\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/formatter.scss",
    "content": "dl {\n    width: auto;\n    font-family: initial;\n    display: grid;\n    grid-template-columns: auto max-content;\n    gap: 0 1em;\n    padding: 1em 0;\n    border-top: 1px solid;\n    border-bottom: 1px solid;\n    margin: 2em 0;\n  }\n\n  dt {\n    grid-column-start: 1;\n    margin: 0 !important;\n  }\n\n  dd {\n    grid-column-start: 2;\n    margin: 0 0 1em 0 !important;\n    &:before {\n        content: \"• \"\n    }\n  }\n\n  dd + dt {\n      &, & + dd {\n        padding-top: 2em;\n      }\n  }\n"
  },
  {
    "path": "assets/css/articles/ios-13.scss",
    "content": ".conversation {\n    max-width: 50ch;\n    display: block;\n    margin: 0 auto;\n    padding: 1em 0;\n    p {\n        margin: 0;\n    }\n\n    p:nth-of-type(2n) {\n        display: block;\n        font-style: italic;\n        text-align: right;\n        padding: 0.5em 0 1em 1em;\n        &::first-letter {\n            font-style: normal;\n        }\n    }\n}\n\n#on-device-speech-recognition-supported-languages {\n    text-align: left;\n\n    dl{\n        display: grid;\n        gap: 1em 2em;\n        grid-template-columns: repeat(1fr);\n      }\n\n      dt {\n        grid-column-start: 1;\n        margin: 0;\n        padding: 0;\n        text-align: right;\n      }\n\n      dd {\n        grid-column-start: 2;\n        margin: 0;\n        padding: 0;\n      }\n}\n"
  },
  {
    "path": "assets/css/articles/keyvaluepairs.scss",
    "content": "#bagua {\n  td {\n    text-align: center;\n  }\n}\n\n#bagua + p ruby:last-of-type {\n  -webkit-ruby-position: under;\n  ruby-position: under;\n}\n\nrtc {\n  display: none !important;\n}\n"
  },
  {
    "path": "assets/css/articles/mapkit-js.scss",
    "content": "#jwt-debug {\n  h3 {\n    margin: 0;\n\n    small {\n      display: block;\n      font-weight: normal;\n      font-size: smaller;\n    }\n  }\n\n  display: grid;\n  grid-template:\n    \"encoded header\"\n    \"encoded payload\"\n    \"encoded signature\";\n  grid-template-columns: repeat(2, 1fr);\n  grid-template-rows: repeat(3, 1fr);\n  gap: 0.5em 3em;\n\n  #jwt-encoded {\n    grid-area: encoded;\n\n    .highlight {\n      font-size: larger;\n      height: 86%;\n    }\n  }\n\n  #jwt-header {\n    grid-area: header;\n\n    span.s2 {\n      color: var(--pink) !important;\n    }\n  }\n\n  #jwt-payload {\n    grid-area: payload;\n\n    span.s2 {\n      color: var(--purple) !important;\n    }\n  }\n\n  #jwt-signature {\n    grid-area: signature;\n\n    span.s2,\n    span.nx {\n      color: var(--teal) !important;\n    }\n  }\n\n  #jwt-header,\n  #jwt-payload,\n  #jwt-signature {\n    .highlight {\n      font-size: smaller;\n    }\n  }\n}\n\n#map {\n  display: block;\n  width: 100%;\n  height: 400px;\n  margin-bottom: 2em;\n}\n\n.mk-map-view {\n  border: 1px transparent solid;\n  border-radius: 4px;\n}\n\n@media screen and (max-width: 768px) {\n  #jwt-debug {\n    grid-template:\n      \"encoded\"\n      \"header\"\n      \"payload\"\n      \"signature\";\n    grid-template-columns: auto;\n    grid-template-rows: auto;\n    gap: 0.5em 0;\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/message-id.scss",
    "content": "@import \"../functions\";\n\n@media screen and (min-width: 768px) {\n  aside {\n    @include clearfix;\n\n    figure {\n      float: right;\n      padding-left: 20px;\n      margin: 0 !important;\n      padding: 0 !important;\n\n      img {\n        margin: 0 !important;\n      }\n\n      & + p:first-of-type {\n        margin-top: 2em;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/metrickit.scss",
    "content": "h2 {\n  clear: both;\n}\n\n@media screen and (min-width: 768px) {\n  #battery-usage {\n    float: right;\n    width: 300px;\n    padding-left: 20px;\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/model-context-protocol.scss",
    "content": "ol {\n    list-style-type: decimal !important;\n}\n\n@media (min-width: 768px) {\n    dl {\n        margin-left: auto;\n        margin-right: auto;\n        width: 85%;\n    }\n\n    dt,\n    dd {\n        padding-left: 2rem;\n        padding-right: 2rem;\n    }\n}\n\ndl {\n    border: 1px solid #b7b7b7;\n    padding: 1rem;\n    margin-top: 0.25rem;\n    margin-bottom: 3rem;\n    font-size: 0.8rem;\n\n    dt,\n    dd {\n        padding-left: 1rem;\n        padding-right: 1rem;\n    }\n\n    dd {\n        margin-left: 0;\n    }\n\n    dt {\n        padding-top: 1rem;\n        margin-bottom: 0.125rem;\n\n        &:first-of-type {\n            padding-top: 0;\n        }\n    }\n}\n\n.user {\n    text-align: left;\n}\n\n.client {\n    text-align: center;\n}\n\n.assistant {\n    text-align: right;\n\n    blockquote {\n        text-align: right !important;\n        border-left: 0;\n    }\n}\n\n[role=\"article\"] .content dl blockquote {\n    text-align: right !important;\n    border-left: 0 !important;\n    margin: 0;\n    font-style: italic;\n}\n\nspan.big {\n    font-size: 2rem;\n    padding-top: 0.5rem;\n    display: inline-block;\n}\n\npicture img[src$=\".svg\"] {\n    filter: none !important;\n}\n\n#imcp-logo {\n    max-width: 480px;\n    display: block;\n    margin: 0 auto;\n    cursor: pointer;\n}\n\n#emcee-logo {\n    max-width: 480px;\n    display: block;\n    margin: 0 auto;\n    cursor: pointer;\n}"
  },
  {
    "path": "assets/css/articles/swift-format.scss",
    "content": "div.variable-width {\n  resize: horizontal;\n  overflow: hidden;\n  min-width: 30ch;\n  width: 30ch;\n  max-width: 100%;\n  margin-bottom: 2em;\n\n  .highlight {\n    height: 80vh;\n    overflow: scroll;\n    font-size: 14px !important;\n    line-height: 1.2 !important;\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/swift-log.scss",
    "content": "#log-levels {\n  table-layout: auto;\n  tbody td:first-of-type {\n    background-color: var(--color);\n    code {\n      background-color: var(--background);\n      color: var(--text) !important;\n      display: block;\n    }\n  }\n}\n\n#log-level-trace {\n  --color: var(--gray);\n}\n\n#log-level-debug {\n  --color: var(--blue);\n}\n\n#log-level-info {\n  --color: var(--green);\n}\n\n#log-level-notice {\n  --color: var(--yellow);\n}\n\n#log-level-warning {\n  --color: var(--orange);\n}\n\n#log-level-error {\n  --color: var(--red);\n}\n\n#log-level-critical {\n  --color: black;\n}\n"
  },
  {
    "path": "assets/css/articles/swift-package-registry.scss",
    "content": "table {\n  table-layout: auto !important;\n\n  td {\n    text-align: right !important;\n  }\n}\n\n.dialogue {\n  text-align: left !important;\n  margin: 1em auto;\n\n  code,\n  samp {\n    display: inline-block;\n    line-height: 1.6;\n  }\n\n  var.placeholder {\n    padding: 0 0.25em;\n  }\n\n  code {\n    color: var(--code);\n\n    i {\n      color: var(--gray);\n      font-style: normal;\n    }\n  }\n\n  details {\n    margin: 0.5em 0;\n    padding: 0.5em 0;\n    padding-left: 2em;\n    border-top: 1px dotted var(--separator);\n    border-bottom: 1px dotted var(--separator);\n\n    summary {\n      margin-left: -2em;\n      margin-bottom: 0;\n    }\n  }\n\n  pre {\n    width: auto;\n    display: block;\n    clear: both;\n    margin: 0;\n  }\n\n  samp {\n    overflow: none;\n    line-height: 1.2;\n    color: var(--gray);\n    margin-bottom: 0.5em;\n    padding: 0.25em 0;\n    font-style: italic;\n  }\n\n  .placeholder {\n    color: var(--gray) !important;\n  }\n}\n\n@media screen and (min-width: 768px) {\n  .dialogue,\n  details {\n    &::after {\n      content: \"\";\n      clear: both;\n      display: table;\n    }\n  }\n\n  .dialogue {\n    padding: 0.5em 2em !important;\n\n    .input {\n      text-align: left;\n    }\n\n    .output {\n      float: right;\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/articles/swiftui-previews.scss",
    "content": ".code-with-automatic-preview {\n  display: flex;\n  align-items: stretch;\n  background-color: var(--secondary-background);\n  margin-bottom: 2em;\n\n  .highlight {\n    flex: 2;\n  }\n\n  aside {\n    flex: 1;\n    max-width: 400px;\n    border-left: 1px var(--opaque-separator) solid;\n    background-color: var(--secondary-background);\n    margin-left: 20px;\n    padding: 10px;\n  }\n}\n"
  },
  {
    "path": "assets/css/fonts/_batang.scss",
    "content": "@font-face {\n    font-family: 'Batang';\n    src: url(font_path(\"Batang.woff2\")) format(\"woff2\"),\n        url(font_path(\"Batang.woff\")) format(\"woff\");\n    font-weight: normal;\n    font-style: normal;\n    font-display: auto;\n    unicode-range: U+AC00-D7A3, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;\n}\n"
  },
  {
    "path": "assets/css/fonts/_cc.scss",
    "content": "@font-face {\n  font-family: \"Creative Commons Symbols\";\n  src: url(font_path(\"CreativeCommonsSymbols.woff2\")) format(\"woff2\"),\n    url(font_path(\"CreativeCommonsSymbols.woff\")) format(\"woff\");\n  font-weight: normal;\n  font-style: normal;\n  unicode-range: U+1F10D-1F10F, U+1F16D-1F16F;\n}\n"
  },
  {
    "path": "assets/css/fonts/_merriweather.scss",
    "content": "@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Regular\"), local(\"Merriweather-Regular\"),\n        url(font_path(\"Merriweather-Regular.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-Regular.woff\")) format(\"woff\");\n    font-weight: normal;\n    font-style: normal;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Light\"), local(\"Merriweather-Light\"),\n        url(font_path(\"Merriweather-Light.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-Light.woff\")) format(\"woff\");\n    font-weight: 300;\n    font-style: normal;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Black\"), local(\"Merriweather-Black\"),\n        url(font_path(\"Merriweather-Black.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-Black.woff\")) format(\"woff\");\n    font-weight: 900;\n    font-style: normal;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Bold\"), local(\"Merriweather-Bold\"),\n        url(font_path(\"Merriweather-Bold.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-Bold.woff\")) format(\"woff\");\n    font-weight: bold;\n    font-style: normal;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Black Italic\"), local(\"Merriweather-BlackItalic\"),\n        url(font_path(\"Merriweather-BlackItalic.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-BlackItalic.woff\")) format(\"woff\");\n    font-weight: 900;\n    font-style: italic;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Italic\"), local(\"Merriweather-Italic\"),\n        url(font_path(\"Merriweather-Italic.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-Italic.woff\")) format(\"woff\");\n    font-weight: normal;\n    font-style: italic;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Bold Italic\"), local(\"Merriweather-BoldItalic\"),\n        url(font_path(\"Merriweather-BoldItalic.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-BoldItalic.woff\")) format(\"woff\");\n    font-weight: bold;\n    font-style: italic;\n    font-display: auto;\n}\n\n@font-face {\n    font-family: \"Merriweather\";\n    src: local(\"Merriweather Light Italic\"), local(\"Merriweather-LightItalic\"),\n        url(font_path(\"Merriweather-LightItalic.woff2\")) format(\"woff2\"),\n        url(font_path(\"Merriweather-LightItalic.woff\")) format(\"woff\");\n    font-weight: 300;\n    font-style: italic;\n    font-display: auto;\n}\n"
  },
  {
    "path": "assets/css/media-queries/_hover.scss",
    "content": "@media (hover: none) {\n    #logo #mustache {\n        animation-iteration-count: 1;\n    }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_inverted-colors.scss",
    "content": "@media (inverted-colors) {\n    * {\n        text-shadow: none !important;\n        box-shadow: none !important;\n    }\n\n    img {\n        filter: invert(100%);\n    }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_monochrome.scss",
    "content": "@media (monochrome),\n  print and (not(color)),\n  (prefers-contrast: high),\n  screen and (-ms-high-contrast: active) {\n  :root {\n    --red: black;\n    --yellow: black;\n    --green: black;\n    --teal: black;\n    --blue: black;\n    --indigo: black;\n    --purple: black;\n    --pink: black;\n    --gray: black;\n    --gray2: black;\n    --gray3: black;\n    --gray4: black;\n    --gray5: black;\n    --gray6: black;\n\n    --text: black;\n    --secondary-text: black;\n    --placeholder-text: black;\n    --separator: black;\n    --opaque-separator: black;\n    --fill: white;\n    --secondary-fill: white;\n    --background: white;\n    --secondary-background: white;\n  }\n\n  .highlight {\n    color: black !important;\n    background: #fff !important;\n\n    border: 2px black solid;\n\n    .c,\n    .ch,\n    .cm,\n    .cpf,\n    .c1,\n    .cs,\n    .ge,\n    .s,\n    .sa,\n    .sb,\n    .sc,\n    .dl,\n    .sd,\n    .s2,\n    .sh,\n    .sx,\n    .sr,\n    .s1,\n    .ss {\n      font-style: italic;\n    }\n\n    .k,\n    .gh,\n    .gp,\n    .gs,\n    .gu,\n    .kc,\n    .kd,\n    .kn,\n    .kr,\n    .nc,\n    .ni,\n    .ne,\n    .nn,\n    .nt,\n    .ow {\n      font-weight: bold;\n    }\n\n    .se,\n    .si {\n      font-weight: bold;\n      font-style: italic;\n    }\n  }\n\n  .admonition:before {\n    visibility: hidden;\n  }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_prefers-color-scheme.scss",
    "content": "@media (prefers-color-scheme: dark) {\n  :root {\n    --red: rgb(255, 69, 58);\n    --yellow: rgb(255, 214, 10);\n    --green: rgb(48, 209, 88);\n    --teal: rgb(100, 210, 255);\n    --blue: rgb(10, 132, 255);\n    --indigo: rgb(94, 92, 230);\n    --purple: rgb(191, 90, 242);\n    --pink: rgb(255, 55, 95);\n    --gray: rgb(142, 142, 147);\n    --gray2: rgb(99, 99, 102);\n    --gray3: rgb(72, 72, 74);\n    --gray4: rgb(58, 58, 60);\n    --gray5: rgb(44, 44, 46);\n    --gray6: rgb(28, 28, 30);\n\n    --text: rgb(255, 255, 255);\n    --secondary-text: rgb(235, 235, 245);\n    --placeholder-text: rgb(235, 235, 245);\n    --separator: rgb(84, 84, 88);\n    --opaque-separator: rgb(56, 56, 58);\n    --fill: rgb(120, 120, 128);\n    --secondary-fill: rgb(120, 120, 128);\n    --background: rgb(14, 14, 15);\n    --secondary-background: rgb(28, 28, 30);\n  }\n\n  @supports (color: color(display-p3 1 1 1)) {\n    :root {\n      --red: color(display-p3 1 0.4118 0.3804);\n      --yellow: color(display-p3 1 0.8314 0.149);\n      --green: color(display-p3 0.1882 0.8588 0.3569);\n      --teal: color(display-p3 0.4392 0.8431 1);\n      --blue: color(display-p3 0.251 0.6118 1);\n      --indigo: color(display-p3 0.4902 0.4784 1);\n      --purple: color(display-p3 0.8549 0.5608 1);\n      --pink: color(display-p3 1 0.3922 0.5098);\n      --gray: color(display-p3 0.6824 0.6824 0.698);\n      --gray2: color(display-p3 0.4863 0.4863 0.502);\n      --gray3: color(display-p3 0.3294 0.3294 0.3373);\n      --gray4: color(display-p3 0.2667 0.2667 0.2745);\n      --gray5: color(display-p3 0.2118 0.2118 0.2196);\n      --gray6: color(display-p3 0.1412 0.1412 0.149);\n\n      --text: color(display-p3 1 1 1);\n      --secondary-text: color(display-p3 0.9216 0.9216 0.9608);\n      --placeholder-text: color(display-p3 0.9216 0.9216 0.9608);\n      --separator: color(display-p3 0.3294 0.3294 0.3451);\n      --opaque-separator: color(display-p3 0.2196 0.2196 0.2275);\n      --fill: color(display-p3 0.4706 0.4706 0.502);\n      --secondary-fill: color(display-p3 0.4706 0.4706 0.502);\n      --background: color(display-p3 0.0706 0.0706 0.075);\n      --secondary-background: color(display-p3 0.1412 0.1412 0.149);\n    }\n  }\n\n  body {\n    div.highlight {\n      border: 1px var(--separator) solid !important;\n    }\n\n    .language-toggle a {\n      color: var(--secondary-text) !important;\n    }\n\n    .info {\n      background: #333c44 !important;\n    }\n\n    .warning {\n      background: #484131 !important;\n    }\n\n    .error {\n      background: #592e41 !important;\n    }\n  }\n\n  article,\n  i {\n    img[src$=\".svg\"] {\n      filter: invert(100%);\n    }\n  }\n\n  kbd {\n    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 0 2px #222 inset;\n  }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_prefers-contrast.scss",
    "content": "@media (prefers-contrast: high), screen and (-ms-high-contrast: active) {\n  :root {\n    --red: rgb(215, 0, 21);\n    --yellow: rgb(179, 98, 0);\n    --green: rgb(36, 138, 61);\n    --teal: rgb(0, 113, 164);\n    --blue: rgb(0, 64, 221);\n    --indigo: rgb(54, 52, 163);\n    --purple: rgb(137, 68, 171);\n    --pink: rgb(211, 15, 69);\n    --gray: rgb(108, 108, 112);\n    --gray2: rgb(142, 142, 147);\n    --gray3: rgb(174, 174, 178);\n    --gray4: rgb(188, 188, 192);\n    --gray5: rgb(216, 216, 220);\n    --gray6: rgb(235, 235, 240);\n\n    --text: rgb(0, 0, 0);\n    --secondary-text: rgb(60, 60, 67);\n    --placeholder-text: rgb(60, 60, 67);\n    --separator: rgb(60, 60, 67);\n    --opaque-separator: rgb(198, 198, 200);\n    --fill: rgb(120, 120, 128);\n    --secondary-fill: rgb(120, 120, 128);\n    --background: rgb(235, 235, 240);\n    --secondary-background: rgb(255, 255, 255);\n  }\n\n  @supports (color: color(display-p3 1 1 1)) {\n    :root {\n      --red: color(display-p3 0.8431 0 0.08235);\n      --yellow: color(display-p3 0.702 0.3843 0);\n      --green: color(display-p3 0.1412 0.5412 0.2392);\n      --teal: color(display-p3 0 0.4431 0.6431);\n      --blue: color(display-p3 0 0.251 0.8667);\n      --indigo: color(display-p3 0.2118 0.2039 0.6392);\n      --purple: color(display-p3 0.5373 0.2667 0.6706);\n      --pink: color(display-p3 0.8275 0.05882 0.2706);\n      --gray: color(display-p3 0.4235 0.4235 0.4392);\n      --gray2: color(display-p3 0.5569 0.5569 0.5765);\n      --gray3: color(display-p3 0.6824 0.6824 0.698);\n      --gray4: color(display-p3 0.7373 0.7373 0.7529);\n      --gray5: color(display-p3 0.8471 0.8471 0.8627);\n      --gray6: color(display-p3 0.9216 0.9216 0.9412);\n\n      --text: color(display-p3 0 0 0);\n      --secondary-text: color(display-p3 0.2353 0.2353 0.2627);\n      --placeholder-text: color(display-p3 0.2353 0.2353 0.2627);\n      --separator: color(display-p3 0.2353 0.2353 0.2627);\n      --opaque-separator: color(display-p3 0.7765 0.7765 0.7843);\n      --fill: color(display-p3 0.4706 0.4706 0.502);\n      --secondary-fill: color(display-p3 0.4706 0.4706 0.502);\n      --background: color(display-p3 0.9216 0.9216 0.9412);\n      --secondary-background: color(display-p3 1 1 1);\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_prefers-reduced-motion.scss",
    "content": "@media (prefers-reduced-motion: reduce) {\n    #logo #mustache {\n        animation: none !important;\n    }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_print.scss",
    "content": "@media print {\n  @page {\n    margin: 0.5in;\n  }\n\n  @page {\n    @bottom-center {\n      content: \"Page \" counter(page) \" of \" counter(pages);\n      font-size: small;\n    }\n\n    @footnote {\n      border-top: 1pt black solid;\n      padding-top: 1em;\n      font-size: smaller;\n      padding-left: 1.5em;\n    }\n  }\n\n  html {\n    border-top: none;\n\n    body {\n      font-size: 12pt !important;\n    }\n  }\n\n  #logo {\n    height: 3em !important;\n\n    svg {\n      transform: scale(0.5);\n      transform-origin: top left;\n    }\n  }\n\n  img,\n  p,\n  blockquote,\n  aside,\n  ul,\n  ol,\n  table,\n  figure,\n  .highlight-group {\n    page-break-inside: avoid;\n  }\n\n  .highlight-group {\n    page-break-before: avoid;\n  }\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    page-break-before: avoid;\n    page-break-after: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  p {\n    a {\n      word-wrap: break-word;\n    }\n\n    a[href^=\"#\"]:after {\n      display: none;\n    }\n\n    a[href^=\"http://\"]:after,\n    a[href^=\"https://\"]:after {\n      // content: \" (\"attr(href) \")\";\n      // text-decoration: underline;\n      content: \" (\" attr(title) \") \";\n      float: footnote;\n      color: var(--secondary-text);\n      font-size: small;\n      text-decoration: none;\n      text-align: left;\n      page-break-inside: avoid;\n      page-break-before: avoid;\n    }\n  }\n\n  article [title]::after {\n    content: \" (\" attr(title) \") \";\n    float: footnote;\n    font-size: small;\n  }\n\n  .highlight-group a {\n    font-size: 50%;\n  }\n\n  div.highlight {\n    border-radius: 4px;\n    border: 2px black solid;\n  }\n\n  [role=\"article\"] {\n    .content {\n      margin-bottom: 1em !important;\n    }\n  }\n\n  [role=\"complementary\"] {\n    display: none;\n  }\n\n  [role=\"contentinfo\"] {\n    page-break-inside: avoid;\n    font-size: small;\n  }\n\n  .admonition {\n    padding: 0 0 0 1em;\n\n    &::before {\n      visibility: hidden;\n    }\n  }\n\n  [hidden] {\n    display: none !important;\n  }\n}\n\n@media print and (color) {\n  * {\n    -webkit-print-color-adjust: exact;\n    print-color-adjust: exact;\n  }\n}\n"
  },
  {
    "path": "assets/css/media-queries/_width.scss",
    "content": "@media screen and (max-width: 768px) {\n  [role=\"article\"] header {\n    .byline {\n      .authors,\n      .translators {\n        &:after {\n          content: \" \";\n          display: block;\n        }\n      }\n    }\n  }\n\n  .container {\n    padding: 1em;\n  }\n\n  #recent {\n    ul {\n      display: block;\n\n      li {\n        min-height: auto;\n        margin-bottom: 2em;\n\n        .title {\n          display: block;\n          height: auto;\n          padding-bottom: 0.5rem;\n        }\n      }\n    }\n  }\n\n  [role=\"article\"] {\n    font-size: smaller;\n\n    .content {\n      overflow: hidden;\n\n      blockquote {\n        margin: 1em 0;\n      }\n    }\n\n    footer .contributor {\n      width: 100%;\n      margin-bottom: 1em;\n\n      &:not(:first-child) {\n        border-top: none;\n      }\n\n      .avatar {\n        padding: 0;\n      }\n\n      .details {\n        margin-top: 0;\n      }\n    }\n  }\n\n  [role=\"complementary\"] {\n    #continue,\n    #related {\n      width: 100%;\n    }\n\n    #related {\n      margin-top: 1em;\n\n      li {\n        font-size: 1em;\n      }\n    }\n  }\n\n  #contributors ul li {\n    flex-basis: 33%;\n  }\n\n  #recent article {\n    float: none;\n    display: block;\n    width: 100%;\n\n    &:last-child,\n    &:nth-of-type(2n) {\n      margin-right: 0;\n    }\n  }\n\n  .archive dl {\n    width: 100%;\n    margin: 0;\n    float: none;\n\n    dt {\n      margin: 2em 0 0.5em 0;\n    }\n  }\n\n  #archive dd {\n    min-height: 30px;\n  }\n}\n\n@media screen and (max-width: 960px) {\n  [role=\"banner\"] {\n    display: block;\n    margin-bottom: 0;\n    padding-bottom: 0;\n\n    #logo {\n      margin: 0 !important;\n      height: auto;\n\n      svg {\n        width: 25vw;\n        display: block;\n        margin: 0 auto 1.5em auto;\n      }\n\n      padding-bottom: 0.5em;\n    }\n\n    .tagline {\n      font-size: 4.4vw;\n      padding-bottom: 2em;\n    }\n  }\n\n  #recent {\n    ul {\n      grid-template-columns: repeat(2, 1fr);\n    }\n  }\n\n  .anchor {\n    font-size: smaller;\n  }\n\n  #announcement {\n    margin-left: 0;\n    margin-right: 0;\n  }\n\n  article.author,\n  article.translator {\n    header {\n      display: block;\n\n      .avatar {\n        margin: 0 auto 1em auto;\n        display: block;\n      }\n\n      h1 {\n        text-align: center;\n      }\n    }\n  }\n}\n\n@media screen and (max-width: 768px) {\n  #promotion {\n    padding-top: 3em;\n\n    small {\n      position: relative;\n      top: 60px;\n    }\n\n    article {\n      padding-top: 80px;\n    }\n\n    .book {\n      img {\n        width: 350px;\n        margin: -86px auto 0 280px;\n        position: absolute;\n      }\n    }\n\n    .buy {\n      width: 100%;\n    }\n  }\n}\n\n@media screen and (max-width: 480px) {\n  #promotion {\n    padding-top: 0;\n\n    small {\n      text-align: center;\n      display: block;\n    }\n\n    article {\n      overflow: hidden;\n    }\n\n    h3 {\n      padding-right: 3em;\n    }\n\n    .book {\n      margin: -30px 0 0 0;\n      img {\n        width: 320px;\n        margin: 0;\n        padding: 0;\n        position: relative;\n        left: -10px;\n      }\n\n      & + div {\n        clear: both;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/css/screen.scss",
    "content": "@charset \"UTF-8\";\n\n@import \"colors\";\n@import \"animations\";\n@import \"typography\";\n@import \"admonitions\";\n@import \"layout\";\n@import \"code\";\n@import \"inputs\";\n\n@import \"media-queries/width\";\n@import \"media-queries/hover\";\n@import \"media-queries/inverted-colors\";\n@import \"media-queries/monochrome\";\n@import \"media-queries/prefers-color-scheme\";\n@import \"media-queries/prefers-contrast\";\n@import \"media-queries/prefers-reduced-motion\";\n@import \"media-queries/print\";\n\n* {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n#type-encodings tr > td:first-child,\n#method-encodings tr > td:first-child {\n  width: 12em;\n  padding-left: 3em;\n}\n\n@media screen and (max-width: 480px) {\n  #gpuimage table {\n    font-size: 50%;\n  }\n}\n\n#gpuimage {\n  #gpuimage-benchmarks td {\n    text-align: center;\n\n    &:first-child {\n      text-align: left;\n    }\n\n    &:last-child {\n      text-align: right;\n    }\n  }\n\n  #gpuimage-filters td {\n    vertical-align: top;\n    font-size: 75%;\n  }\n\n  blockquote {\n    font-size: 75%;\n  }\n}\n\ntable {\n  &.core-data-versus-nskeyedarchiver td {\n    text-align: center;\n\n    &:first-child {\n      text-align: left;\n      font-weight: bold;\n    }\n  }\n\n  &#xcode-key-bindings-modifiers {\n    width: 100%;\n\n    td,\n    th {\n      width: 20%;\n      text-align: center;\n    }\n  }\n}\n\n#cfstringtransform table {\n  display: block;\n\n  td:first-child {\n    width: 60%;\n  }\n}\n\n#icloud header time {\n  background-color: rgba(255, 128, 0, 0.2);\n}\n\n\n"
  },
  {
    "path": "assets/js/application.js",
    "content": "\"use strict\";\n\n(function() {\n  const delay = 300;\n\n  const keys = {\n    end: 35,\n    home: 36,\n    left: 37,\n    up: 38,\n    right: 39,\n    down: 40\n  };\n\n  const direction = {\n    37: -1,\n    39: 1\n  };\n\n  const tablists = document.querySelectorAll('[role=\"tablist\"]');\n  tablists.forEach(tablist => {\n    const tabs = tablist.querySelectorAll('[role=\"tab\"]');\n    const panels = tablist.parentElement.querySelectorAll('[role=\"tabpanel\"]');\n\n    const clickEventListener = event => {\n      const target = event.target;\n\n      target.dispatchEvent(\n        new Event(\"activate\", {\n          bubbles: true\n        })\n      );\n    };\n\n    const keydownEventListener = event => {\n      const { keyCode } = event;\n\n      switch (keyCode) {\n        case keys.end:\n          event.preventDefault();\n          tabs[tabs.length - 1].dispatchEvent(\n            new Event(\"activate\", {\n              bubbles: true\n            })\n          );\n          break;\n        case keys.home:\n          event.preventDefault();\n          tabs[0].dispatchEvent(\n            new Event(\"activate\", {\n              bubbles: true\n            })\n          );\n          break;\n        case keys.up:\n        case keys.down:\n          determineOrientation(event);\n          break;\n      }\n    };\n\n    const keyupEventListener = event => {\n      const { keyCode, target } = event;\n\n      tabs.forEach(tab => {\n        tab.addEventListener(\"focus\", focusEventListener);\n      });\n\n      if (direction[keyCode]) {\n        if (target.dataset.index !== undefined) {\n          if (tabs[target.dataset.index + direction[pressed]]) {\n            tabs[target.dataset.index + direction[pressed]].focus();\n          } else if (pressed === keys.left || pressed === keys.up) {\n            tabs[tabs.length - 1].focus();\n          } else if (pressed === keys.right || pressed == keys.down) {\n            tabs[0].focus();\n          }\n        }\n      }\n    };\n\n    const focusEventListener = event => {\n      const { target } = event;\n\n      const handler = target => {\n        focused = document.activeElement;\n\n        if (target === focused) {\n          target.dispatchEvent(new Event(\"activate\"));\n        }\n      };\n\n      setTimeout(handler, delay, target);\n    };\n\n    const activateEventListener = event => {\n      const { target, bubbles } = event;\n\n      tabs.forEach(tab => {\n        tab.setAttribute(\"tabindex\", \"-1\");\n        tab.setAttribute(\"aria-selected\", \"false\");\n        tab.removeEventListener(\"focus\", focusEventListener);\n      });\n\n      panels.forEach(panel => {\n        panel.setAttribute(\"hidden\", \"hidden\");\n      });\n\n      target.removeAttribute(\"tabindex\");\n      target.setAttribute(\"aria-selected\", \"true\");\n\n      var controls = target.getAttribute(\"aria-controls\");\n      document.getElementById(controls).removeAttribute(\"hidden\");\n\n      if (bubbles) {\n        for (const language of [\"swift\", \"objective-c\"]) {\n          if (target.classList.contains(language)) {\n            if (window.localStorage) {\n              window.localStorage.setItem(\"preferred-language\", language);\n            }\n\n            document\n              .querySelectorAll(`[role=\"tab\"].${language}`)\n              .forEach(tab => {\n                tab.dispatchEvent(new Event(\"activate\"));\n              });\n\n            document.querySelectorAll(\".highlight-group\").forEach(group => {\n              if (\n                group.clientHeight > (parseInt(group.style.minHeight, 10) || 0)\n              ) {\n                group.style.minHeight = `${group.clientHeight}px`;\n              }\n            });\n          }\n        }\n      }\n    };\n\n    for (let index = 0; index < tabs.length; index++) {\n      const tab = tabs[index];\n      tab.addEventListener(\"click\", clickEventListener);\n      tab.addEventListener(\"keydown\", keydownEventListener);\n      tab.addEventListener(\"keyup\", keyupEventListener);\n      tab.addEventListener(\"activate\", activateEventListener);\n\n      tab.dataset.index = index;\n    }\n  });\n\n  if (window.localStorage) {\n    const language = window.localStorage.getItem(\"preferred-language\");\n    if (language) {\n      document.querySelectorAll(`[role=\"tab\"].${language}`).forEach(tab => {\n        tab.dispatchEvent(new Event(\"activate\"));\n      });\n    }\n  }\n\n  document\n    .querySelectorAll('article [role=\"heading\"] h1.title')\n    .forEach(element => {\n      const resize = () => {\n        const compression = 1.0;\n        const minFontSize = 16.0;\n        const maxFontSize = 72.0;\n\n        element.style.fontSize =\n          Math.max(\n            Math.min(element.clientWidth / (compression * 10), maxFontSize),\n            minFontSize\n          ) + \"px\";\n      };\n\n      resize();\n\n      window.addEventListener(\"resize\", resize);\n      window.addEventListener(\"orientationchange\", resize);\n    });\n})();\n\nsetTimeout(function() {\n  if (\n    document.location.pathname === \"/\" &&\n    matchMedia(\"(hover: none)\").matches\n  ) {\n    document.querySelector(\"#logo svg\").classList.add(\"animated\");\n  }\n}, 1000);\n"
  },
  {
    "path": "assets/js/articles/caemitterlayer.js",
    "content": "// Credit: https://jsfiddle.net/subzey/52sowezj/\n\n'use strict';\n\n(function() {\nvar canvas = document.querySelector('#webgl-confetti canvas');\nvar gl = canvas.getContext('webgl', {alpha: true});\n\nvar vertexShader = gl.createShader(gl.VERTEX_SHADER);\ngl.shaderSource(vertexShader, `\nprecision lowp float;\n\nattribute vec2 a_position;\nattribute float a_startAngle;\nattribute float a_angularVelocity;\nattribute float a_rotationAxisAngle;\nattribute float a_particleDistance;\nattribute float a_particleAngle;\nattribute float a_particleY;\nuniform float u_time;\n\nvarying vec2 v_position;\nvarying vec3 v_color;\nvarying float v_overlight;\n\nvoid main() {\n  float angle = a_startAngle + a_angularVelocity * u_time;\n  float vertPosition = 1.1 - mod(u_time * .25 + a_particleY, 2.2);\n  float viewAngle = a_particleAngle + mod(u_time * .25, 6.28);\n\n  mat4 vMatrix = mat4(1.3, 0.0, 0.0, 0.0, 0.0, 1.3, 0.0, 0.0, 0.0, 0.0, 1.0,\n                      1.0, 0.0, 0.0, 0.0, 1.0);\n\n  mat4 shiftMatrix =\n      mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,\n           a_particleDistance * sin(viewAngle), vertPosition,\n           a_particleDistance * cos(viewAngle), 1.0);\n\n  mat4 pMatrix = mat4(cos(a_rotationAxisAngle), sin(a_rotationAxisAngle), 0.0,\n                      0.0, -sin(a_rotationAxisAngle), cos(a_rotationAxisAngle),\n                      0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) *\n                 mat4(1.0, 0.0, 0.0, 0.0, 0.0, cos(angle), sin(angle), 0.0, 0.0,\n                      -sin(angle), cos(angle), 0.0, 0.0, 0.0, 0.0, 1.0);\n\n  gl_Position =\n      vMatrix * shiftMatrix * pMatrix * vec4(a_position * 0.03, 0.0, 1.0);\n  vec4 normal = vec4(0.0, 0.0, 1.0, 0.0);\n  vec4 transformedNormal = normalize(pMatrix * normal);\n\n  float dotNormal = abs(dot(normal.xyz, transformedNormal.xyz));\n  float regularLighting = dotNormal / 2.0 + 0.5;\n  float glanceLighting = smoothstep(0.92, 0.98, dotNormal);\n  v_color = vec3(mix((0.5 - transformedNormal.z / 2.0) * regularLighting, 1.0,\n                     glanceLighting),\n                 mix(0.5 * regularLighting, 1.0, glanceLighting),\n                 mix((0.5 + transformedNormal.z / 2.0) * regularLighting, 1.0,\n                     glanceLighting));\n\n  v_position = a_position;\n  v_overlight = 0.9 + glanceLighting * 0.1;\n}\n`);\ngl.compileShader(vertexShader);\n\nvar fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\ngl.shaderSource(fragmentShader, `\nprecision lowp float;\nvarying vec2 v_position;\nvarying vec3 v_color;\nvarying float v_overlight;\n\nvoid main() {\n  gl_FragColor =\n      vec4(v_color, 1.0 - smoothstep(0.8, v_overlight, length(v_position)));\n}\n`);\ngl.compileShader(fragmentShader);\n\nvar shaderProgram = gl.createProgram();\ngl.attachShader(shaderProgram, vertexShader);\ngl.attachShader(shaderProgram, fragmentShader);\ngl.linkProgram(shaderProgram);\ngl.useProgram(shaderProgram);\n\ngl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());\n\nvar STRIDE = 8;\nvar attrs = [\n  {name: 'a_position', length: 2, offset: 0},\n  {name: 'a_startAngle', length: 1, offset: 2},\n  {name: 'a_angularVelocity', length: 1, offset: 3},\n  {name: 'a_rotationAxisAngle', length: 1, offset: 4},\n  {name: 'a_particleDistance', length: 1, offset: 5},\n  {name: 'a_particleAngle', length: 1, offset: 6},\n  {name: 'a_particleY', length: 1, offset: 7}\n];\nfor (var i = 0; i < attrs.length; i++) {\n  var name = attrs[i].name;\n  var length = attrs[i].length;\n  var offset = attrs[i].offset;\n  var attribLocation = gl.getAttribLocation(shaderProgram, name);\n  gl.vertexAttribPointer(\n      attribLocation, length, gl.FLOAT, false, STRIDE * 4, offset * 4);\n  gl.enableVertexAttribArray(attribLocation);\n}\n\ngl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());\n\nvar NUM_PARTICLES = 150;\nvar NUM_VERTICES = 4;\nvar NUM_INDICES = 6;\n\nvar vertices = new Float32Array(NUM_PARTICLES * STRIDE * NUM_VERTICES);\nvar indices = new Uint16Array(NUM_PARTICLES * NUM_INDICES);\nfor (var i = 0; i < NUM_PARTICLES; i++) {\n  var axisAngle = Math.random() * Math.PI * 2;\n  var startAngle = Math.random() * Math.PI * 2;\n  var groupPtr = i * STRIDE * NUM_VERTICES;\n\n  var particleDistance = Math.sqrt(Math.random());\n  var particleAngle = Math.random() * Math.PI * 2;\n  var particleY = Math.random() * 2.2;\n  var angularVelocity = Math.random() * 2 + 1;\n\n  for (var j = 0; j < 4; j++) {\n    var vertexPtr = groupPtr + j * STRIDE;\n    vertices[vertexPtr + 2] = startAngle;\n    vertices[vertexPtr + 3] = angularVelocity;\n    vertices[vertexPtr + 4] = axisAngle;\n    vertices[vertexPtr + 5] = particleDistance;\n    vertices[vertexPtr + 6] = particleAngle;\n    vertices[vertexPtr + 7] = particleY;\n  }\n\n  vertices[groupPtr] = vertices[groupPtr + STRIDE * 2] = -1;\n  vertices[groupPtr + STRIDE] = vertices[groupPtr + STRIDE * 3] = 1;\n  vertices[groupPtr + 1] = vertices[groupPtr + STRIDE + 1] = -1;\n  vertices[groupPtr + STRIDE * 2 + 1] = vertices[groupPtr + STRIDE * 3 + 1] = 1;\n\n  var indicesPtr = i * NUM_INDICES;\n  var vertexPtr = i * NUM_VERTICES;\n  indices[indicesPtr] = vertexPtr;\n  indices[indicesPtr + 4] = indices[indicesPtr + 1] = vertexPtr + 1;\n  indices[indicesPtr + 3] = indices[indicesPtr + 2] = vertexPtr + 2;\n  indices[indicesPtr + 5] = vertexPtr + 3;\n}\n\ngl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);\ngl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);\n\nvar timeUniformLocation = gl.getUniformLocation(shaderProgram, 'u_time');\nvar startTime = (window.performance || Date).now();\ngl.enable(gl.BLEND);\ngl.blendFunc(gl.SRC_ALPHA, gl.ONE);\ngl.viewport(0, 0, canvas.width, canvas.height);\n\nfunction frame() {\n  gl.uniform1f(\n      timeUniformLocation,\n      ((window.performance || Date).now() - startTime) / 1000);\n  gl.clear(gl.COLOR_BUFFER_BIT);\n  gl.drawElements(\n      gl.TRIANGLES, NUM_INDICES * NUM_PARTICLES, gl.UNSIGNED_SHORT, 0);\n\n  requestAnimationFrame(frame);\n}\n\nframe();\n})();\n"
  },
  {
    "path": "assets/js/articles/mapkit-js.js",
    "content": "\"use strict\";\n\n(function() {\n  mapkit.init({\n    authorizationCallback: done => {\n      done(\n        \"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IjRUOTJZWlNXR00ifQ.eyJleHAiOjI0MTYzMjE2MDAuMjc2NjE2MSwiaXNzIjoiOUpXVkFEUjNSUSIsIm9yaWdpbiI6Imh0dHBzOlwvXC9uc2hpcHN0ZXIuY29tIiwiaWF0IjoxNTUyMzIxNjAwLjI3NjYxNzF9.DRsKD-6Y9MMVId46PnV9DK-YiobqGu0qCMbK1fYjglWOVnuJkpm4UGDdYLB0T4xJfStPlrSI1Pwbzsjn_i0Qww\"\n      );\n    }\n  });\n\n  const center = new mapkit.Coordinate(37.3327, -122.0053),\n    span = new mapkit.CoordinateSpan(0.0125, 0.0125),\n    region = new mapkit.CoordinateRegion(center, span);\n\n  let map = new mapkit.Map(\"map\", {\n    region: region,\n    showsCompass: mapkit.FeatureVisibility.Hidden,\n    showsZoomControl: false,\n    showsMapTypeControl: false\n  });\n\n  const annotation = new mapkit.MarkerAnnotation(center, {\n    title: \"Apple Park Visitor Center\",\n    subtitle: \"10600 North Tantau Avenue, Cupertino, CA 95014\",\n    glyphText: \"\",\n    color: \"#8e8e93\",\n    displayPriority: 1000\n  });\n\n  map.addAnnotation(annotation);\n})();\n"
  },
  {
    "path": "assets/js/articles/swift-format.js",
    "content": "//= require vendor/resize-observer.min.js\n\n\"use strict\";\n\nfunction getComputedWidthInEm(element) {\n  const computed = window.getComputedStyle(element);\n\n  const regex = /(\\d+(\\.\\d+)?)px$/;\n  const fontSize = Number(computed.fontSize.match(regex)[1]);\n  const width = Number(computed.width.match(regex)[1]);\n  return (width / fontSize) * 2.6;\n}\n\n(function() {\n  const container = document.querySelector(\".variable-width\");\n\n  const candidates = Array.from(document.querySelectorAll(\"[data-width]\")).sort(\n    ({ dataset: { width: a } }, { dataset: { width: b } }) => b.localeCompare(a)\n  );\n\n  const observer = new ResizeObserver(() => {\n    const targetWidth = getComputedWidthInEm(container);\n    var foundMatch = false;\n\n    candidates.forEach(element => {\n      const width = Number(element.dataset.width);\n      if (!width || foundMatch) {\n        element.setAttribute(\"hidden\", \"hidden\");\n      } else if (width < targetWidth) {\n        foundMatch = true;\n        element.removeAttribute(\"hidden\");\n      } else {\n        element.setAttribute(\"hidden\", \"hidden\");\n      }\n    });\n\n    if (!foundMatch) {\n      candidates[candidates.length - 1].removeAttribute(\"hidden\");\n    }\n  });\n\n  observer.observe(container);\n})();\n"
  },
  {
    "path": "assets/js/articles/wwdc-2020.js",
    "content": "\"use strict\";\n\n(function () {\n  const details = document.querySelector(\"details\");\n  if (details) {\n    let listener = details.addEventListener(\"toggle\", (event) => {\n      console.log(\"ADSFADSAFD\");\n      const video = document.querySelector(\"video\");\n      video.loop = true;\n      video.controls = false;\n      video.play();\n      details.removeEventListener(\"toggle\", listener);\n    });\n  }\n})();\n"
  },
  {
    "path": "assets/js/nsmutablehipster.js",
    "content": "//= require vendor/typed.min.js\n\n\"use strict\";\n\n(function() {\n  document.body.contentEditable = true;\n  document.querySelectorAll(\"a\").forEach(element => {\n    element.contentEditable = false;\n  });\n\n  if (document.querySelector(\".tagline\")) {\n    new Typed(\".tagline strong\", {\n      strings: [\"NSHipster\", \"NSMutableHipster\"],\n      typeSpeed: 100,\n      backSpeed: 100,\n      startDelay: 1000,\n      onComplete: () => {\n        document.querySelector(\".typed-cursor\").remove();\n      }\n    });\n\n    document\n      .querySelector(\".typed-cursor\")\n      .setAttribute(\"style\", \"position: absolute;\");\n  }\n})();\n"
  },
  {
    "path": "assets/videos/TrickXORTreat.srt",
    "content": "1\n00:00:02,500 --> 00:00:07,591\nEvery kid knows the phrase, [kid sing-songy] \"Trick or treat!\" But have you\n\n2\n00:00:07,691 --> 00:00:11,882\never stopped to wonder — what kind of _\"or\"_ is that, exactly?\n\n3\n00:00:13,566 --> 00:00:20,150\nLet's start with the obvious interpretation: Two circles—two children. Orange means\n\n4\n00:00:20,250 --> 00:00:25,063\ntreats, gray means tricks. This is inclusive OR: If any child\n\n5\n00:00:25,163 --> 00:00:29,976\nknocks, everyone gets candy. Only an empty porch gets tricks.\n\n6\n00:00:30,076 --> 00:00:33,306\n[quickly] [chuckles] Is this how Venn diagrams work? Not at all!\n\n7\n00:00:33,406 --> 00:00:36,323\nBut hey, it's Halloween—logic gets to wear a costume, too.\n\n8\n00:00:37,323 --> 00:00:40,651\n[title] Trick AND Treat Both children must show up together, or\n\n9\n00:00:40,751 --> 00:00:44,459\nnobody gets treats. [sarcastic] One lonely kid? Sorry, that's a trick.\n\n10\n00:00:45,459 --> 00:00:50,925\n[title] Trick XOR Treat This house rewards exactly one visitor.\n\n11\n00:00:51,025 --> 00:00:55,077\nToo few or too many, and everyone gets tricked.\n\n12\n00:00:57,377 --> 00:01:00,878\nThese three behaviors cover most houses on the block.\n\n13\n00:01:00,978 --> 00:01:04,140\nBut De Morgan's laws hint at something more... a\n\n14\n00:01:04,240 --> 00:01:08,353\ntheoretical complement to each. A spooky, inverted reflection.\n\n15\n00:01:08,953 --> 00:01:14,882\n[spooky] What cursed operations lurk in the penumbra of reason?\n\n16\n00:01:14,982 --> 00:01:19,380\nLet's face our fears and venture into the dark.\n\n17\n00:01:21,069 --> 00:01:24,576\n[title] Trick NOR Treat: the Halloween hater. This neighbor\n\n18\n00:01:24,676 --> 00:01:27,938\nonly gives treats when nobody visits. [quick laugh] The\n\n19\n00:01:28,038 --> 00:01:29,955\nonly winning move is not to play.\n\n20\n00:01:30,955 --> 00:01:36,134\n[title] Trick NAND Treat: NOT-AND—the reverse psychology neighbor. This\n\n21\n00:01:36,234 --> 00:01:40,521\nhouse gives treats to everyone... except pairs. Come alone?\n\n22\n00:01:40,621 --> 00:01:44,833\nTreats. Don't come at all? ...[chuckles] Also Treats. Come\n\n23\n00:01:44,933 --> 00:01:49,219\ntogether? [mischievous] That's the only way to get tricked.\n\n24\n00:01:50,219 --> 00:01:55,675\n[title] Trick XNOR Treat: the conformity enforcer—XOR inverted. This neighbor\n\n25\n00:01:55,775 --> 00:02:00,148\nrewards matching behavior. Both kids visit, or both stay home?\n\n26\n00:02:00,248 --> 00:02:03,755\nTreats. Just one kid? [judgmental] That's a trick.\n\n27\n00:02:06,555 --> 00:02:11,086\nThese bottom-row operations are... deeply strange. They're the\n\n28\n00:02:11,186 --> 00:02:15,268\nkinds of houses you'd skip entirely. But mathematically?\n\n29\n00:02:15,368 --> 00:02:18,106\nThey're just as valid as the classics.\n\n30\n00:02:18,705 --> 00:02:20,877\nSo the next time a child asks [kid sing-songy]\n\n31\n00:02:20,977 --> 00:02:23,742\n\"trick or treat?\", you now have the mathematically correct\n\n32\n00:02:23,842 --> 00:02:27,940\nresponse: [annoying high-pitched nasal pedantic] \"That depends—which logical operator\n\n33\n00:02:28,040 --> 00:02:31,249\nare you implementing?\" [quick laugh] ...though I wouldn't recommend\n\n34\n00:02:31,349 --> 00:02:33,521\nit if you don't want your house getting egged.\n\n"
  },
  {
    "path": "collections/en/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: Croath Liu\nemail: Croath.Liu@gmail.com\nurl: https://twitter.com/cr0ath\ntwitter: cr0ath\ngithub: croath\nimage: croath-liu.jpg\n---\n\n[Croath Liu](http://croath.com) ([@cr0ath](https://twitter.com/cr0ath)) is an iOS developer and one of the [lead translators](https://nshipster.cn/translators/croath-liu/) for [nshipster.cn](https://nshipster.cn/). He lives in Beijing.\n"
  },
  {
    "path": "collections/en/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](https://delisa.me)\n([@kattrali](https://twitter.com/kattrali))\nis the creator of the Xcode Package Manager,\n[Alcatraz](https://alcatraz.io),\nas well as a [CocoaPods](https://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/en/_authors/em-lazer-walker.md",
    "content": "---\ntitle: Em Lazer-Walker\n\nname: Em Lazer-Walker\nemail: hi@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: em-lazer-walker.jpg\n---\n\n[Em Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) \nmakes experimental games, interactive art, and software tools.\n"
  },
  {
    "path": "collections/en/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/en/_authors/jemmons.md",
    "content": "---\ntitle: \"@jemmons\"\nname: jemmons\nurl: https://figure.ink\ntwitter: jemmons\ngithub: jemmons\nimage: jemmons.jpg\n---\n\nJosh ([@jemmons](https://twitter.com/jemmons)) has led mobile development at\ngraphic.ly, Reverb, and now Retail Zipline.\nHe lives in Chicago and writes about Swift at [figure.ink](https://figure.ink).\n"
  },
  {
    "path": "collections/en/_authors/jordan-morgan.md",
    "content": "---\ntitle: Jordan Morgan\n\nname: Jordan Morgan\nemail: info@dreaminginbinary.co\nurl: https://dreaminginbinary.co\ntwitter: JordanMorgan10\ngithub: JordanMorgan10\nimage: jordan-morgan.jpg\n---\n\nJordan Morgan is a software developer from Ozark, who created\n[Dreaming In Binary](https://dreaminginbinary.co)\nas a creative outlet for his side projects.\nCurrently, he is an iOS engineer at [Buffer](https://buffer.com).\nJordan is focused on helping the community by\ndoing talks about iOS and remote work and\nwriting books and blogs posts,\nand considers himself a lifelong student for all forms of software engineering.\n"
  },
  {
    "path": "collections/en/_authors/matt-massicotte.md",
    "content": "---\ntitle: Matt Massicotte\n\nname: Matt Massicotte\nurl: https://www.massicotte.org\ngithub: mattmassicotte\nimage: matt-massicotte.jpg\n---\n\n[Matt](https://www.massicotte.org/about) \nis a long-time developer for Apple platforms. \nHe's into programming, the outdoors, video games, music, \nand progress towards a safe and fair world for all people.\n"
  },
  {
    "path": "collections/en/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\n"
  },
  {
    "path": "collections/en/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/en/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/en/_authors/reda-lemeden.md",
    "content": "---\ntitle: Reda Lemeden\n\nname: Reda Lemeden\nemail: hello@redalemeden.com\nurl: https://redalemeden.com\ntwitter: kaishin\ngithub: kaishin\nimage: reda-lemeden.jpg\n---\n\n[Reda Lemeden](https://redalemeden.com) is a UI designer and developer making software on both Apple platforms and the Web. He has a penchant for layout engines, grids, and color theory.\n"
  },
  {
    "path": "collections/en/_authors/zoe-smith.md",
    "content": "---\ntitle: Zoë Smith\n\nname: Zoë Smith\nemail: zoews@me.com\nurl: https://zoesmith.io/about\ntwitter: zoejessica\ngithub: zoejessica\nimage: zoe-smith.jpg\n---\n\n[Zoë Smith](https://zoesmith.io/about)\n[(@zoejessica)](https://twitter.com/zoejessica)\nis a software developer for Apple platforms\nand the creator of\n[AccessControlKitty](https://github.com/zoejessica/accesscontrolkitty) and\n[F\\*\\*\\*ingIfCaseLetSyntax.com](http://fuckingifcaseletsyntax.com).\n"
  },
  {
    "path": "collections/en/_books/cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: http://schema.org/Discontinued\nprice: 29.00\nnumber_of_pages: 296\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\ndate: 2014-06-03\n---\n"
  },
  {
    "path": "collections/en/_books/fake-book-objective-c.md",
    "content": "---\nname: \"fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\navailability: http://schema.org/Discontinued\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19\nnumber_of_pages: 115\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\ndate: 2014-06-03\n---\n"
  },
  {
    "path": "collections/en/_books/flight-school-guide-to-swift-codable.md",
    "content": "---\nname: flight-school-guide-to-swift-codable\ntitle: Flight School Guide to Swift Codable\nshort_title: Flight School\nsub_title: Guide to Swift Codable\nauthor: Mattt\nsummary: >-\n  Make better apps with less code more quickly using Swift Codable.\nimage: flight-school-guide-to-swift-codable.svg\navailability: http://schema.org/InStock\nbook_url: https://flightdotschool.com/books/codable\nprice: 29.00\nnumber_of_pages: 140\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-1-949080-04-9\ndate: 2018-04-20\n---\n"
  },
  {
    "path": "collections/en/_books/flight-school-guide-to-swift-numbers.md",
    "content": "---\nname: flight-school-guide-to-swift-numbers\ntitle: Flight School Guide to Swift Numbers\nshort_title: Flight School\nsub_title: Guide to Swift Numbers\nauthor: Mattt\nsummary: >-\n  Everything you need to know about working with numbers in Swift\nimage: flight-school-guide-to-swift-numbers.svg\navailability: http://schema.org/InStock\nbook_url: https://flightdotschool.com/books/numbers\nprice: 29.00\nnumber_of_pages: 120\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-1-949080-05-6\ndate: 2018-06-01\n---\n"
  },
  {
    "path": "collections/en/_books/flight-school-guide-to-swift-strings.md",
    "content": "---\nname: flight-school-guide-to-swift-strings\ntitle: Flight School Guide to Swift Strings\nshort_title: Flight School\nsub_title: Guide to Swift Strings\nauthor: Mattt\nsummary: >-\n  A comprehensive reference for working with text in Swift and Foundation.\nimage: flight-school-guide-to-swift-strings.svg\navailability: http://schema.org/InStock\nbook_url: https://flightdotschool.com/books/strings\nprice: 29.00\nnumber_of_pages: 180\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-1-949080-08-7\ndate: 2019-02-01\n---\n"
  },
  {
    "path": "collections/en/_books/nshipster.md",
    "content": "---\nname: nshipster\ntitle: \"NSHipster: Obscure Topics in Objective-C, Swift, & Cocoa\"\nshort_title: \"NSHipster\"\nsub_title: \"Obscure Topics in Objective-C, Swift, & Cocoa\"\nedition: 3<sup>rd</sup> Edition\nauthor: Mattt\nsummary: >-\n  A hand-picked selection of articles and essays from NSHipster.com,\n  bound together in a single volume for convenient reference.\n\nimage: nshipster-obscure-topics-third-edition.png\navailability: http://schema.org/InStock\nbook_url: https://gumroad.com/l/nshipster-third-edition-digital-only\nprice: 9.00\nnumber_of_pages: 389\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-1-949080-26-1\ndate: 2019-12-17\n---\n"
  },
  {
    "path": "collections/es/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: Croath Liu\nemail: Croath.Liu@gmail.com\nurl: https://twitter.com/cr0ath\ntwitter: cr0ath\ngithub: croath\nimage: croath-liu.jpg\n---\n\n[Croath Liu](http://croath.com) ([@cr0ath](https://twitter.com/cr0ath)) is an iOS developer and one of the [lead translators](https://nshipster.cn/translators/croath-liu/) for [nshipster.cn](https://nshipster.cn/). He lives in Beijing.\n"
  },
  {
    "path": "collections/es/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](https://delisa.me)\n([@kattrali](https://twitter.com/kattrali))\nis the creator of the Xcode Package Manager,\n[Alcatraz](https://alcatraz.io),\nas well as a [CocoaPods](https://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/es/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/es/_authors/jordan-morgan.md",
    "content": "---\ntitle: Jordan Morgan\n\nname: Jordan Morgan\nemail: info@dreaminginbinary.co\nurl: https://dreaminginbinary.co\ntwitter: JordanMorgan10\ngithub: JordanMorgan10\nimage: jordan-morgan.jpg\n---\n\nJordan Morgan is a software developer from Ozark, who created\n[Dreaming In Binary](https://dreaminginbinary.co)\nas a creative outlet for his side projects.\nCurrently, he is an iOS engineer at [Buffer](https://buffer.com).\nJordan is focused on helping the community by\ndoing talks about iOS and remote work and\nwriting books and blogs posts,\nand considers himself a lifelong student for all forms of software engineering.\n"
  },
  {
    "path": "collections/es/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\ngoogle: 106751358503565042647\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\nHe is the founder of NSHipster and [Flight School](https://flightdotschool.com),\nand the creator of several open source libraries,\nincluding [AFNetworking](https://github.com/afnetworking/afnetworking)\nand [Alamofire](https://github.com/alamofire/alamofire).\n"
  },
  {
    "path": "collections/es/_authors/mike-lazer-walker.md",
    "content": "---\ntitle: Mike Lazer-Walker\n\nname: Mike Lazer-Walker\nemail: michael@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: mike-lazer-walker.jpg\n---\n\n[Mike Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) is an independent app and game developer, and the creator of [F\\*\\*\\*ing Block Syntax](http://goshdarnblocksyntax.com). He frequently writes about engineering and design on his [blog](http://blog.lazerwalker.com).\n"
  },
  {
    "path": "collections/es/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/es/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/es/_books/01-nshipster-swift.md",
    "content": "---\nname: nshipster-swift\ntitle: \"NSHipster: Obscure Topics in Cocoa & Swift\"\nshort_title: \"NSHipster, Second Edition\"\nsub_title: \"Obscure Topics in Cocoa & Swift\"\nauthor: Mattt & Nate Cook\nsummary: \"Revised and extended to focus on using Swift in iOS and OS X development, NSHipster: Obscure Topics in Cocoa & Swift is an essential updated guide.\"\nimage: \"nshipster-swift-cover@2x.png\"\nformats:\n  ebook:\n    isbn: 978-0-9912182-6-4\navailability: in_stock\nbook_url: https://gum.co/nshipster-swift/\nprice: 29.00\nnumber_of_pages: 288\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-6-4\ndate: 2015-04-18\n---\n"
  },
  {
    "path": "collections/es/_books/02-cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/cfhipsterref\nprice: 29.00\nnumber_of_pages: 296\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/es/_books/03-nshipster-fake-book-objective-c.md",
    "content": "---\nname: \"nshipster-fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19\nnumber_of_pages: 115\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/es/_translators/juan-fernandez-sagasti.md",
    "content": "---\ntitle: Juan F. Sagasti\nname: Juan F. Sagasti\nurl: https://theam.io\ntwitter: https://www.twitter.com/jfsagasti\ngithub: https://github.com/jfsagasti\nimage: juan-fernandez-sagasti.jpg\n---\n\n[Juan F. Sagasti](https://www.twitter.com/jfsagasti) es ingeniero de software y cofundador en [Theam](https://theam.io). Colabora como traductor principal en español de NSHipster. Vive con su gata Lily en una bonita isla del Atlántico llamada Gran Canaria.\n"
  },
  {
    "path": "collections/fr/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: Croath Liu\nemail: Croath.Liu@gmail.com\nurl: https://twitter.com/cr0ath\ntwitter: cr0ath\ngithub: croath\nimage: croath-liu.jpg\n---\n\n[Croath Liu](http://croath.com) ([@cr0ath](https://twitter.com/cr0ath)) is an iOS developer and one of the [lead translators](https://nshipster.cn/translators/croath-liu/) for [nshipster.cn](https://nshipster.cn/). He lives in Beijing.\n"
  },
  {
    "path": "collections/fr/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](https://delisa.me)\n([@kattrali](https://twitter.com/kattrali))\nis the creator of the Xcode Package Manager,\n[Alcatraz](https://alcatraz.io),\nas well as a [CocoaPods](https://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/fr/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/fr/_authors/jordan-morgan.md",
    "content": "---\ntitle: Jordan Morgan\n\nname: Jordan Morgan\nemail: info@dreaminginbinary.co\nurl: https://dreaminginbinary.co\ntwitter: JordanMorgan10\ngithub: JordanMorgan10\nimage: jordan-morgan.jpg\n---\n\nJordan Morgan is a software developer from Ozark, who created\n[Dreaming In Binary](https://dreaminginbinary.co)\nas a creative outlet for his side projects.\nCurrently, he is an iOS engineer at [Buffer](https://buffer.com).\nJordan is focused on helping the community by\ndoing talks about iOS and remote work and\nwriting books and blogs posts,\nand considers himself a lifelong student for all forms of software engineering.\n"
  },
  {
    "path": "collections/fr/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\ngoogle: 106751358503565042647\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\nHe is the founder of NSHipster and [Flight School](https://flightdotschool.com),\nand the creator of several open source libraries,\nincluding [AFNetworking](https://github.com/afnetworking/afnetworking)\nand [Alamofire](https://github.com/alamofire/alamofire).\n"
  },
  {
    "path": "collections/fr/_authors/mike-lazer-walker.md",
    "content": "---\ntitle: Mike Lazer-Walker\n\nname: Mike Lazer-Walker\nemail: michael@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: mike-lazer-walker.jpg\n---\n\n[Mike Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) is an independent app and game developer, and the creator of [F\\*\\*\\*ing Block Syntax](http://goshdarnblocksyntax.com). He frequently writes about engineering and design on his [blog](http://blog.lazerwalker.com).\n"
  },
  {
    "path": "collections/fr/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/fr/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/fr/_books/01-nshipster-swift.md",
    "content": "---\nname: nshipster-swift\ntitle: \"NSHipster: Obscure Topics in Cocoa & Swift\"\nshort_title: \"NSHipster, Second Edition\"\nsub_title: \"Obscure Topics in Cocoa & Swift\"\nauthor: Mattt & Nate Cook\nsummary: \"Revised and extended to focus on using Swift in iOS and OS X development, NSHipster: Obscure Topics in Cocoa & Swift is an essential updated guide.\"\nimage: \"nshipster-swift-cover@2x.png\"\nformats:\n  ebook:\n    isbn: 978-0-9912182-6-4\navailability: in_stock\nbook_url: https://gum.co/nshipster-swift/\nprice: 29.00\nnumber_of_pages: 288\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-6-4\ndate: 2015-04-18\n---\n"
  },
  {
    "path": "collections/fr/_books/02-cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/cfhipsterref\nprice: 29.00\nnumber_of_pages: 296\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/fr/_books/03-nshipster-fake-book-objective-c.md",
    "content": "---\nname: \"nshipster-fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19\nnumber_of_pages: 115\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/fr/_translators/vincent-pradeilles.md",
    "content": "---\ntitle: Vincent \nname: Vincent Pradeilles\ntwitter: https://www.twitter.com/v_pradeilles\ngithub: https://github.com/vincent-pradeilles\nimage: vincent-pradeilles.jpg\n---\n\n[Vincent Pradeilles](https://www.twitter.com/v_pradeilles) est dévelopeur iOS chez [Worldline](https://worldline.com) à Lyon. Il collabore à NSHipster en tant que traducteur français.\n"
  },
  {
    "path": "collections/ko/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: Croath Liu\nemail: Croath.Liu@gmail.com\nurl: https://twitter.com/cr0ath\ntwitter: cr0ath\ngithub: croath\nimage: croath-liu.jpg\n---\n\n[Croath Liu](http://croath.com) ([@cr0ath](https://twitter.com/cr0ath)) is an iOS developer and one of the [lead translators](https://nshipster.cn/translators/croath-liu/) for [nshipster.cn](https://nshipster.cn/). He lives in Beijing.\n"
  },
  {
    "path": "collections/ko/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](http://delisa.me) ([@kattrali](https://twitter.com/kattrali)) is the creator of the Xcode Package Manager, [Alcatraz](http://alcatraz.io), as well as a [CocoaPods](http://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/ko/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/ko/_authors/jemmons.md",
    "content": "---\ntitle: \"@jemmons\"\nname: jemmons\nurl: https://figure.ink\ntwitter: jemmons\ngithub: jemmons\nimage: jemmons.jpg\n---\n\nJosh ([@jemmons](https://twitter.com/jemmons)) has led mobile development at\ngraphic.ly, Reverb, and now Retail Zipline.\nHe lives in Chicago and writes about Swift at [figure.ink](https://figure.ink).\n"
  },
  {
    "path": "collections/ko/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\ngoogle: 106751358503565042647\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\nHe is the founder of NSHipster and [Flight School](https://flightdotschool.com),\nand the creator of several open source libraries,\nincluding [AFNetworking](https://github.com/afnetworking/afnetworking)\nand [Alamofire](https://github.com/alamofire/alamofire).\n"
  },
  {
    "path": "collections/ko/_authors/mike-lazer-walker.md",
    "content": "---\ntitle: Mike Lazer-Walker\n\nname: Mike Lazer-Walker\nemail: michael@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: mike-lazer-walker.jpg\n---\n\n[Mike Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) is an independent app and game developer, and the creator of [F\\*\\*\\*ing Block Syntax](http://goshdarnblocksyntax.com). He frequently writes about engineering and design on his [blog](http://blog.lazerwalker.com).\n"
  },
  {
    "path": "collections/ko/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/ko/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/ko/_books/01-nshipster-swift.md",
    "content": "---\nname: nshipster-swift\ntitle: \"NSHipster: Obscure Topics in Cocoa & Swift\"\nshort_title: \"NSHipster, Second Edition\"\nsub_title: \"Obscure Topics in Cocoa & Swift\"\nauthor: Mattt & Nate Cook\nsummary: \"Revised and extended to focus on using Swift in iOS and OS X development, NSHipster: Obscure Topics in Cocoa & Swift is an essential updated guide.\"\nimage: \"nshipster-swift-cover@2x.png\"\nformats:\n  ebook:\n    isbn: 978-0-9912182-6-4\navailability: in_stock\nbook_url: https://gum.co/nshipster-swift/\nprice: 29.00\nnumber_of_pages: 288\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-6-4\ndate: 2015-04-18\n---\n"
  },
  {
    "path": "collections/ko/_books/02-cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/cfhipsterref\nprice: 29.00\nnumber_of_pages: 296\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/ko/_books/03-nshipster-fake-book-objective-c.md",
    "content": "---\nname: \"nshipster-fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19\nnumber_of_pages: 115\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/ko/_translators/pilgwon.md",
    "content": "---\ntitle: 김필권\n\nname: 김필권\nemail: rlavlfrnjs12@gmail.com\nurl: https://blog.pilgwon.app\ngithub: pilgwon\ntwitter: pilgwon\nimage: pilgwon.jpg\n---\n\n[Pilgwon](https://nshipster.co.kr/translators/pilgwon)([@pilgwon](https://twitter.com/pilgwon)) is an iOS developer in Seoul, South Korea. And the creator of [GROOV](https://itunes.apple.com/us/app/groov/id1138262409?mt=8). He translates about iOS on his [blog](https://blog.pilgwon.app) more than once a week. He loves making Insanely Great services. He is lead translator for [nshipster.co.kr](https://nshipster.co.kr).\n"
  },
  {
    "path": "collections/ru/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: Croath Liu\nemail: Croath.Liu@gmail.com\nurl: https://twitter.com/cr0ath\ntwitter: cr0ath\ngithub: croath\nimage: croath-liu.jpg\n---\n\n[Croath Liu](http://croath.com) ([@cr0ath](https://twitter.com/cr0ath)) is an iOS developer and one of the [lead translators](https://nshipster.cn/translators/croath-liu/) for [nshipster.cn](https://nshipster.cn/). He lives in Beijing.\n"
  },
  {
    "path": "collections/ru/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](https://delisa.me)\n([@kattrali](https://twitter.com/kattrali))\nis the creator of the Xcode Package Manager,\n[Alcatraz](https://alcatraz.io),\nas well as a [CocoaPods](https://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/ru/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/ru/_authors/jordan-morgan.md",
    "content": "---\ntitle: Jordan Morgan\n\nname: Jordan Morgan\nemail: info@dreaminginbinary.co\nurl: https://dreaminginbinary.co\ntwitter: JordanMorgan10\ngithub: JordanMorgan10\nimage: jordan-morgan.jpg\n---\n\nJordan Morgan is a software developer from Ozark, who created\n[Dreaming In Binary](https://dreaminginbinary.co)\nas a creative outlet for his side projects.\nCurrently, he is an iOS engineer at [Buffer](https://buffer.com).\nJordan is focused on helping the community by\ndoing talks about iOS and remote work and\nwriting books and blogs posts,\nand considers himself a lifelong student for all forms of software engineering.\n"
  },
  {
    "path": "collections/ru/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\ngoogle: 106751358503565042647\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\nHe is the founder of NSHipster and [Flight School](https://flightdotschool.com),\nand the creator of several open source libraries,\nincluding [AFNetworking](https://github.com/afnetworking/afnetworking)\nand [Alamofire](https://github.com/alamofire/alamofire).\n"
  },
  {
    "path": "collections/ru/_authors/mike-lazer-walker.md",
    "content": "---\ntitle: Mike Lazer-Walker\n\nname: Mike Lazer-Walker\nemail: michael@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: mike-lazer-walker.jpg\n---\n\n[Mike Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) is an independent app and game developer, and the creator of [F\\*\\*\\*ing Block Syntax](http://goshdarnblocksyntax.com). He frequently writes about engineering and design on his [blog](http://blog.lazerwalker.com).\n"
  },
  {
    "path": "collections/ru/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/ru/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/ru/_books/01-nshipster-swift.md",
    "content": "---\nname: nshipster-swift\ntitle: \"NSHipster: Obscure Topics in Cocoa & Swift\"\nshort_title: \"NSHipster, Second Edition\"\nsub_title: \"Obscure Topics in Cocoa & Swift\"\nauthor: Mattt & Nate Cook\nsummary: \"Revised and extended to focus on using Swift in iOS and OS X development, NSHipster: Obscure Topics in Cocoa & Swift is an essential updated guide.\"\nimage: \"nshipster-swift-cover@2x.png\"\nformats:\n  ebook:\n    isbn: 978-0-9912182-6-4\navailability: in_stock\nbook_url: https://gum.co/nshipster-swift/\nprice: 29.00\nnumber_of_pages: 288\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-6-4\ndate: 2015-04-18\n---\n"
  },
  {
    "path": "collections/ru/_books/02-cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/cfhipsterref\nprice: 29.00\nnumber_of_pages: 296\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/ru/_books/03-nshipster-fake-book-objective-c.md",
    "content": "---\nname: \"nshipster-fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19\nnumber_of_pages: 115\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\ndate: 2014-06-03\n\n---\n"
  },
  {
    "path": "collections/zh-Hans/_authors/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: \"Croath Liu\"\nemail: Croath.Liu@gmail.com\nurl: https://croath.com\ntwitter: croath\ngithub: croath\ngoogle: 108566152424457191834\nimage: \"croath-liu.jpg\"\n---\n\n云游四海的工程师\n"
  },
  {
    "path": "collections/zh-Hans/_authors/delisa-mason.md",
    "content": "---\ntitle: Delisa Mason\n\nname: Delisa Mason\nemail: delisa.mason@gmail.com\nurl: https://twitter.com/kattrali\ntwitter: kattrali\ngithub: kattrali\nimage: delisa-mason.jpg\n---\n\n[Delisa Mason](https://delisa.me)\n([@kattrali](https://twitter.com/kattrali))\nis the creator of the Xcode Package Manager,\n[Alcatraz](https://alcatraz.io),\nas well as a [CocoaPods](https://cocoapods.org) Core Team member.\n"
  },
  {
    "path": "collections/zh-Hans/_authors/jack-flintermann.md",
    "content": "---\ntitle: Jack Flintermann\n\nname: Jack Flintermann\nemail: jack@stripe.com\nurl: https://twitter.com/jflinter\ntwitter: jflinter\ngithub: jflinter\nimage: jack-flintermann.jpg\n---\n\n[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.\n"
  },
  {
    "path": "collections/zh-Hans/_authors/mattt.md",
    "content": "---\ntitle: Mattt\n\nname: Mattt\nemail: mattt@nshipster.com\nurl: https://twitter.com/mattt\ntwitter: mattt\ngithub: mattt\ngoogle: 106751358503565042647\nimage: mattt.jpg\n---\n\n[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))\nis a writer and developer in Portland, Oregon.\nHe is the founder of NSHipster and [Flight School](https://flightdotschool.com),\nand the creator of several open source libraries,\nincluding [AFNetworking](https://github.com/afnetworking/afnetworking)\nand [Alamofire](https://github.com/alamofire/alamofire).\n"
  },
  {
    "path": "collections/zh-Hans/_authors/mike-lazer-walker.md",
    "content": "---\ntitle: Mike Lazer-Walker\n\nname: Mike Lazer-Walker\nemail: michael@lazerwalker.com\nurl: https://twitter.com/lazerwalker\ntwitter: lazerwalker\ngithub: lazerwalker\nimage: mike-lazer-walker.jpg\n---\n\n[Mike Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker)) is an independent app and game developer, and the creator of [F\\*\\*\\*ing Block Syntax](http://goshdarnblocksyntax.com). He frequently writes about engineering and design on his [blog](http://blog.lazerwalker.com).\n"
  },
  {
    "path": "collections/zh-Hans/_authors/natasha-murashev.md",
    "content": "---\ntitle: Natasha Murashev\n\nname: Natasha Murashev\nemail: natasha@natashatherobot.com\nurl: https://twitter.com/NatashaTheRobot\ntwitter: NatashaTheRobot\ngithub: NatashaTheRobot\nimage: natasha-murashev.jpg\n---\n\nNatasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))\nis an iOS developer by day and a robot by night.\nShe organizes the\n[try! Swift Conference](https://www.tryswift.co)\naround the world.\nShe's currently living the digital nomad life as her alter identity:\n[@NatashaTheNomad](https://twitter.com/natashathenomad).\n"
  },
  {
    "path": "collections/zh-Hans/_authors/nate-cook.md",
    "content": "---\ntitle: Nate Cook\n\nname: Nate Cook\nemail: nate@nshipster.com\nurl: https://twitter.com/nnnnnnnn\ntwitter: nnnnnnnn\ngithub: natecook1000\nimage: nate-cook.jpg\n---\n\n[Nate Cook](http://natecook.com) ([@nnnnnnnn](https://twitter.com/nnnnnnnn)) is an independent web and application developer who [writes frequently about topics in Swift](http://natecook.com/blog/), and the creator of [SwiftDoc.org](http://swiftdoc.org).\n"
  },
  {
    "path": "collections/zh-Hans/_books/01-nshipster-swift.md",
    "content": "---\nname: nshipster-swift\ntitle: \"NSHipster: Obscure Topics in Cocoa & Swift\"\nshort_title: \"NSHipster, Second Edition\"\nsub_title: \"Obscure Topics in Cocoa & Swift\"\nauthor: Mattt & Nate Cook\nsummary: \"Revised and extended to focus on using Swift in iOS and OS X development, NSHipster: Obscure Topics in Cocoa & Swift is an essential updated guide.\"\nimage: \"nshipster-swift-cover@2x.png\"\nformats:\n  ebook:\n    isbn: 978-0-9912182-6-4\navailability: in_stock\nbook_url: https://gum.co/nshipster-swift/\nprice: 29\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-6-4\n---\n"
  },
  {
    "path": "collections/zh-Hans/_books/02-cfhipsterref.md",
    "content": "---\nname: cfhipsterref\ntitle: \"CFHipsterRef: Low-Level Programming on iOS & OS X\"\nshort_title: \"CFHipsterRef\"\nsub_title: \"Low-Level Programming on iOS & OS X\"\nauthor: Mattt\nsummary: \"Perfect for intermediate and expert developers wanting to take a deeper dive into advanced topics, _CFHipsterRef: Low-Level Programming on iOS & OS X_ covers the core technologies powering Cocoa, Objective-C, and the operating system itself, including Grand Central Dispatch, Accelerate, and the Objective-C runtime.\"\nimage: \"cfhipsterref-cover@2x.png\"\navailability: in_stock\nbook_url: https://gum.co/cfhipsterref\nprice: 29.99\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-4-0\n---\n"
  },
  {
    "path": "collections/zh-Hans/_books/03-nshipster-fake-book-objective-c.md",
    "content": "---\nname: \"nshipster-fake-book-objective-c\"\ntitle: \"The NSHipster Fake Book (Objective-C)\"\nauthor: Mattt\nsummary: \"Over 200 code samples, ranging from the beginner and basic to the expert and obscure, across a variety of genres and use cases. Without any needless explanation.\"\nimage: \"the-nshipster-fake-book-cover@2x.png\"\nformats:\n  pdf:\n    price: 19.99\n    isbn: ...\navailability: in_stock\nbook_url: https://gum.co/the-nshipster-fake-book\nprice: 19.99\ncategory: Media > Books > Non-Fiction > Technology Books\nisbn: 978-0-9912182-1-9\n---\n"
  },
  {
    "path": "collections/zh-Hans/_translators/Candyan.md",
    "content": "---\ntitle: Candyan\n\nname: \"Candyan\"\nemail: liuyanhp@gmail.com\nurl: https://candyan.com\ngithub: candyan\n---\n\n[Candyan](https://candyan.com) 专业 iOS，业余 Android，偶尔捣鼓下Server的工程师。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/andrew-yang.md",
    "content": "---\ntitle: Andrew Yang\n\nname: \"Andrew Yang\"\nemail: younthu@gmail.com\nurl: http://blog.ilibrary.me\ngithub: younthu\n---\n\niOS 开发者，11 年之前做过很长时间 windows 后台程序的开发。很喜欢移动应用开发，发布过一些小应用，有一个[个人网站](http://blog.ilibrary.me)，你可以尝试和网站上的机器人聊天，希望你不要失望。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/april-peng.md",
    "content": "---\ntitle: April Peng\n\nname: \"April Peng\"\nemail: april.pyl@gmail.com\nurl: http://aprilme.com\ngithub: aprilnov\n---\n\n做 iOS / Mac / Web 开发的大白羊妹子~\n"
  },
  {
    "path": "collections/zh-Hans/_translators/chester-liu.md",
    "content": "---\ntitle: Chester Liu\n\nname: \"Chester Liu\"\nemail: skyline75489@outlook.com\ngravatar: 64edfde4a55cef57f9d47d42acbcaf48\ngithub: skyline75489\ntwitter: ChesterLiu2\n---\n\niOS 工程师，一直想成为更好的自己。我的 [Github](https://github.com/skyline75489) 和 [StackOverflow](https://stackoverflow.com/users/3562486/skyline75489)。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/croath-liu.md",
    "content": "---\ntitle: Croath Liu\n\nname: \"Croath Liu\"\nemail: Croath.Liu@gmail.com\nurl: https://croath.com\ntwitter: croath\ngithub: croath\ngoogle: 108566152424457191834\ngravatar: 720e8ba099f10eca25dd87ef5afe4aa7\n---\n\n云游四海的工程师\n"
  },
  {
    "path": "collections/zh-Hans/_translators/david-liu.md",
    "content": "---\ntitle: David Liu\n\nname: \"David Liu\"\nemail: xingruo.liu@gmail.com\ntwitter: davydliu\ngithub: davydliu\ngravatar: 7085efed913ec6d5186e7c57352acfbd\n---\n\n混迹于美帝的工程师，户外运动爱好者。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/henry-lee.md",
    "content": "---\ntitle: Henry Lee\n\nname: \"Henry Lee\"\nemail: leelejia@gmail.com\nurl: http://lejia.li\ngithub: lilejia\ngravatar: 97b4cc7deef9a17bef19a13dc2a033a4\n---\n\n爱好广泛的 iOS 工程师。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/ricky-tan.md",
    "content": "---\ntitle: Ricky Tan\n\nname: \"Ricky Tan\"\nemail: ricky.tan.xin@gmail.com\nurl: https://xcoder.tips\ngravatar: 71f0bbfbb3b0bc7e6e9aa2187814196a\ngithub: rickytan\ngoogle: +rickytanx\n---\n\nRicky Tan 是一位来自杭州的 iOS 开发者，毕业于浙江大学，早期参与开发浙大校园应用 [iZJU](https://itunes.apple.com/cn/app/izju/id573810521?mt=8) iOS 版。另外开源了一个反响不错的 Xcode 插件 [RTImageAssets](https://github.com/rickytan/RTImageAssets)，及一个导航器 [RTRootNavigationController](https://github.com/rickytan/RTRootNavigationController) 。更多其他内容请[点我](https://github.com/rickytan?tab=repositories)。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/steven-wang.md",
    "content": "---\ntitle: Steven Wang\n\nname: \"Steven Wang\"\nemail: mobilefellow@outlook.com\ngithub: mobilefellow\ngravatar: d05f1e723ced114014820ed9d9aa42ba\n---\n\niOS 开发者，热爱移动开发，喜欢 Swift 语言。曾经四处漂流，现定居杭州。\n"
  },
  {
    "path": "collections/zh-Hans/_translators/tiny-tian.md",
    "content": "---\ntitle: change2hao\nname: \"Tiny Tian\"\nemail: lwtiandev@gmail.com\nurl: http://devtian.me\ngravatar: 5b77b0456447e9040bc35a001b9f3611\ntwitter: change2hao\ngithub: change2hao\n---\n\niOS开发工程师，爱技术，爱生活。"
  },
  {
    "path": "contribute.json",
    "content": "{\n  \"name\": \"NSHipster.com\",\n  \"description\": \"A journal of the overlooked bits in Objective-C, Swift, and Cocoa. Updated weekly.\",\n  \"repository\": {\n    \"url\": \"https://github.com/nshipster/nshipster.com\",\n    \"license\": \"MIT\"\n  },\n  \"keywords\": [\"Ruby\", \"Jekyll\"]\n}\n"
  },
  {
    "path": "feed.xml",
    "content": "---\nlayout: null\n---\n\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xml:lang=\"{{ site.lang }}\">\n    <link href=\"{{ page.url | absolute_url }}\" rel=\"self\" type=\"application/atom+xml\" />\n    <link href=\"{{ '/' | absolute_url }}\" rel=\"alternate\" type=\"text/html\" hreflang=\"{{ site.lang }}\"/>\n    <updated>{{ site.time | date_to_xmlschema }}</updated>\n    <id>{{ page.url | absolute_url | xml_escape }}</id>\n\n    <title>{{ site.title | strip_html | xml_escape | strip }}</title>\n    <subtitle>{{ site.description | markdownify | strip_html }}</subtitle>\n\n    {% if site.author %}\n    <author>\n        <name>{{ site.author.name | default: site.author | xml_escape }}</name>\n        {% if site.author.email %}\n        <email>{{ site.author.email | xml_escape }}</email>\n        {% endif %}\n        {% if site.author.url %}\n        <uri>{{ site.author.url | absolute_url | xml_escape }}</uri>\n        {% endif %}\n    </author>\n    {% endif %}\n\n    {% assign sorted_posts = site.posts | sort: 'updated_on' | reverse %}\n    {% for post in sorted_posts limit: 10 %}\n    <entry>\n        <title type=\"html\">{{ post.title | smartify | strip_html | normalize_whitespace | xml_escape }}</title>\n        <link href=\"{{ post.url | absolute_url }}\" rel=\"alternate\" type=\"text/html\" title=\"{{ post.title | xml_escape }}\" />\n        <published>{{ post.date | date_to_xmlschema }}</published>\n        <updated>{{ post.last_revised_on | default: post.date | date_to_xmlschema }}</updated>\n        <id>{{ post.id | absolute_url | xml_escape }}</id>\n        <content type=\"html\" xml:base=\"{{ post.url | absolute_url | xml_escape }}\">\n            {{ post.content | strip | xml_escape }}\n        </content>\n\n        {% assign author = site.authors | where:\"name\", post.author | first | default: site.author %}\n        <author>\n            <name>{{ author.name | default: \"\" | xml_escape }}</name>\n            {% if author.email %}\n            <email>{{ author.email | xml_escape }}</email>\n            {% endif %}\n            {% if author.url %}\n            <uri>{{ author.url | absolute_url | xml_escape }}</uri>\n            {% endif %}\n        </author>\n\n        {% if post.category and post.category != empty %}\n        <category term=\"{{ post.category | xml_escape }}\" />\n        {% endif %}\n\n        {% for tag in post.tags %}\n        <category term=\"{{ tag | xml_escape }}\" />\n        {% endfor %}\n\n        {% if post.excerpt and post.excerpt != empty %}\n        <summary type=\"html\">{{ post.excerpt | markdownify | normalize_whitespace | xml_escape }}</summary>\n        {% endif %}\n    </entry>\n    {% endfor %}\n</feed>\n"
  },
  {
    "path": "flight-school.md",
    "content": "---\nlayout: post\ndate: 2019-02-01\ntitle: Flight School\nauthor: Mattt\ncategory: \"\"\nexcerpt: >-\n  A new book series for advanced Swift developers\n  from the creators of NSHipster,\n  with comprehensive guides for Codable, Numbers, and Strings.\n  Now updated for Swift 5 and available in print.\nstatus:\n  swift: n/a\n---\n\n[Flight School](https://flightdotschool.com)\nis a book series for advanced Swift developers\nthat explores essential topics in iOS and macOS development\nthrough concise, focused guides.\n\nToday, I'm excited to announce updates to our guides to\n[Swift Codable](https://flightdotschool.com/books/codable) and\n[Numbers](https://flightdotschool.com/books/numbers),\nas well as a brand new\n[Guide to Swift Strings](https://flightdotschool.com/books/strings).\nEverything is up-to-date with the latest from Swift 5 and Xcode 10.2,\nand now --- _for the first time_ --- available in print!\n\nIf you like NSHipster and are looking for something a bit longer,\nI think you're gonna love what Flight School has to offer.\n\n---\n\n{% if site.lang == \"en-US\" %}\n{::nomarkdown type=\"html\"}\n\n<section id=\"publications\">\n  <div class=\"books\">\n  {% include book.html book=\"flight-school-guide-to-swift-codable\" %}\n  {% include book.html book=\"flight-school-guide-to-swift-numbers\" %}\n  {% include book.html book=\"flight-school-guide-to-swift-strings\" %}\n  </div>\n</section>\n\n{:/}\n{% endif %}\n\n## Why I'm Writing Flight School\n\nAs software developers,\nour jobs require us to learn a variety of different\nplatforms, programming languages, frameworks, and tools.\nIn spite of their differences,\nmost technologies share a common foundation in concepts\nlike floating-point arithmetic, data interchange, and string encoding ---\nthe kinds of things you might find in a typical\nComputer Science curriculum.\n\nBut for those of us who came into programming from unconventional backgrounds,\n(for instance, I studied philosophy and linguistics as an undergraduate),\nthe weight of all of this can feel overwhelming at times.\nAnd even if you did study CS in college,\nit may be hard to relate the theory of your coursework\n(what you can remember of it, anyway)\nto the realities of your day job.\n\nI'm writing [Flight School](https://flightdotschool.com)\nto explore important concepts in software development\nin a way that's informative, accessible, and entertaining.\n\nEach book is short enough to be read over a weekend\n(or perhaps coffee breaks over the course of a work week).\nEach chapter is filled with practical information that's backed by examples\nthat you can experiment with for yourself in Xcode Playgrounds.\n\nThe forthcoming [_Guide to Strings_](https://flightdotschool.com/books/strings)\nis our newest and most ambitious release yet,\ncovering everything from the Unicode® standard and Swift 5 `String` internals\nto binary-to-text encoding, parser generators, and natural language processing.\nIf you've ever felt like you wanted to get a handle on text _once and for all_,\nthis is the book for you.\n\nIt'll be available to download next Friday, February 8th,\nand you can pre-order a copy for yourself and download a sample chapter now.\n\n---\n\nThe response from Flight School readers since launching earlier last year\nhas been overwhelming,\nand I couldn't be more excited to share this with everyone.\n\nI look forward to continuing to share new and interesting things\non NSHipster and Flight School,\nand thank you for your continued support. 🧡\n"
  },
  {
    "path": "index.html",
    "content": "---\ntitle: NSHipster\npermalink: /\n---\n\n{% assign sorted_posts = site.posts | sort: 'updated_on' | reverse %}\n{% assign latest_post = sorted_posts.first %}\n<section id=\"latest\">\n  <article>\n    <header>\n      <h1 class=\"title\">\n        <a href=\"{{ latest_post.url }}\">{{ latest_post.title | strip_html | escape | camel_break }}</a>\n      </h1>\n    </header>\n\n    {{ latest_post.excerpt | markdownify }}\n\n    <a class=\"readmore\" href=\"{{ latest_post.url }}\">{% t continue_reading %}</a>\n  </article>\n</section>\n\n{% if sorted_posts.size > 3 %}\n<section id=\"recent\">\n  <h1>{% t recent_articles %}</h1>\n\n  <ul>\n    {% for post in sorted_posts offset:1 limit: 6 %}\n      <li>\n        <a class=\"title\" href=\"{{ post.url }}\">{{ post.title | strip_html | escape | camel_break }}</a>\n\n        {{ post.excerpt | markdownify }}\n      </li>\n    {% endfor %}\n  </ul>\n</section>\n{% endif %}\n\n<section id=\"archive\" class=\"archive\" role=\"navigation\">\n  {% for group in site.groups %}\n    {% for category in site.categories %}\n      {% assign category_name = category[0] %}\n      {% if category_name != group %}\n          {% continue %}\n      {% endif %}\n      <dl>\n        <dt>{{ category_name | default: \"Miscellaneous\" }}</dt>\n        {% for posts in category offset: 1 %}\n           {% assign sorted = posts | sort: \"title\" %}\n           {% for post in sorted %}\n              {% unless post.retired %}\n              <dd><a href=\"{{ post.url }}\">{{ post.title | strip_html | escape | camel_break }}</a></dd>\n              {% endunless %}\n           {% endfor %}\n        {% endfor %}\n      </dl>\n    {% endfor %}\n  {% endfor %}\n</section>\n"
  },
  {
    "path": "return.md",
    "content": "---\nlayout: post\ndate: 2018-07-09\ntitle: Returning to Our Regularly Scheduled Programming\nauthor: Mattt\ncategory: \"\"\nretired: true\nexcerpt: NSHipster returns to weekly publication,\n  with new articles every Monday,\n  updates every Wednesday,\n  and new trivia questions every Friday.\nstatus:\n  swift: n/a\n---\n\nWhen the iPhone SDK first came out,\nthere was a disconnect between how futuristic the iPhone was\nand how, well... _not_ Objective-C was.\n\nFor many new developers,\nObjective-C was seen as an ugly, obscure language ---\nsomething you merely put up with\nin exchange for the privilege of developing on this amazing new platform.\nThat was certainly the case for me when I wrote my first app.\nBut over time,\nI learned to appreciate the beauty of the language and its frameworks.\n\nI started NSHipster in July 2012\nas a way to share my newfound passion.\nAt the time,\nthe term \"hipster\" was tossed around frequently as a casual pejorative\nfor people who ironically enjoyed obscure or bad things.\nWhat better term for someone excited about Objective-C, right?\nRather than being ashamed or annoyed by the language we used in our day-to-day,\nit felt good to turn it around and say\n\"Oh, this? It's an obscure API. You've probably never heard of it.\"\n\n---\n\nToday marks six years since I first launched NSHipster\n(which is a big milestone for all of you out there counting in\n[base-6](https://www.seximal.net)).\nTo mark the occasion,\nI'm very excited to announce my return as the managing editor of NSHipster.\n\nI'm extremely thankful to [Nate Cook](https://nshipster.com/authors/nate-cook/)\nfor his stewardship of NSHipster.\nDuring my tenure at Apple from 2015 to 2018,\nI was unable to contribute to the site;\nit's entirely thanks to him that NSHipster exists today.\nHis contributions to Swift are extraordinary and immeasurable,\nand we all benefit immensely as a community from his work.\n\n## What to Expect\n\n**NSHipster is a celebration of small details\nthat come from big ideas.**\nIt stands at that fabled intersection of liberal arts and technology,\nwhere we can collectively geek out about\nthoughtful abstractions and clever optimizations.\n\nOur focus will continue to be Objective-C and Swift,\nand Apple platforms like macOS and iOS.\nAnd we'll also look at any other languages or technologies\nthat can help us make insanely great software.\n\nBut most importantly,\nwe'll be returning to a regular publishing schedule.\n\nHere's what that will look like:\n\n### New Articles Every Monday\n\nEvery Monday,\nI want you to be able to visit the site\n(or refresh your feed reader)\nand learn something new.\nIt could be topical and directly applicable to what you're working on right now.\nIt might be something you hadn't heard of before, and decide to research further.\nOr maybe its a different way of thinking about a problem.\n\nWe'll start this week with an article\nthat ostensibly falls into any of those three categories:\n[Swift GYB](https://nshipster.com/swift-gyb/)\n\n> This time around,\n> I'd like to open things up more for external contributors.\n> If you have a topic that you'd like to write about on NSHipster,\n> please submit a quick, 3–5 sentence, pitch to\n> [mattt@nshipster.com](mailto:mattt@nshipster.com).\n\n### Updated Articles Every Wednesday\n\nWith nearly 150 articles dating as far back as 2012,\nthere's a lot of material on NSHipster that needs to be revisited.\nOut of date, sample code (mostly Swift),\nchanges in behavior that impact the documentation,\nentirely new APIs that need to be addressed...\n\nWe'll have updates every Wednesday\nuntil we run out of outdated material (😂).\n\n### Trivia Questions Every Friday\n\nThe annual NSHipster pub quizzes at WWDC\nwas one of our favorite events of the year.\nHundreds of developers came out and formed small teams\n(with hilarious team names)\nto answer trivia questions about APIs, language features, and Apple lore.\nFor example, here's one of the tougher question\nfrom the [last quiz we did](https://nshipster.com/nshipster-quiz-8/):\n\n---\n\n**Question**: After Chris Lattner,\nwho was the second contributor to Swift?\n\n{::nomarkdown}\n\n<details>\n<summary><strong>Answer</strong></summary>\n<p><a href=\"https://github.com/apple/swift/commit/023c9cc431e1b67c83ab9c8763b01dd4d8de972e\">Doug Gregor</a></p>\n</details>\n{:/}\n\n---\n\nWe're excited to make these kinds of trivia questions a regular feature\nand share them with everyone.\n[Follow us on Twitter](https://twitter.com/nshipster)\nto take our weekly NSHipster quiz.\n\n## What's Different Right Now\n\nYou might have noticed a few changes since your last visit.\n\nHere's a recap of what we've been working on for today's announcement:\n\n### Upgraded Site Infrastructure\n\nA lot's changed about the internet since NSHipster first launched.\nThe web is significantly faster and more secure,\nthanks to new standards like HTTP/2\nand the widespread adoption of SSL.\n\nIn the weeks leading up to today's relaunch,\nI quietly got to work upgrading NSHipster's tech stack:\n\n- Both [NSHipster.com](https://nshipster.com)\n  and [NSHipster.cn](https://nshipster.cn)\n  are now hosted by [Netlify](https://www.netlify.com),\n  which has been an absolute joy to use.\n  Everything is served from a global CDN\n  (using HTTP/2 if your browser supports it)\n  to ensure that the site loads fast, no matter where you are.\n- NSHipster is now served exclusively using HTTPS\n  thanks to [Let's Encrypt](https://letsencrypt.org).\n- Server responses now include fancy new security headers like\n  [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) and\n  [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security).\n- All of the image assets were re-optimized with the latest version of\n  [ImageOptim](https://imageoptim.com/mac),\n  which reduced file size by ~30% across the board.\n- Critical CSS is now inlined to optimize the site's\n  [Critical Rendering Path](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/).\n- And most important of all,\n  the site now\n  [supports the iPhone X notch](https://webkit.org/blog/7929/designing-websites-for-iphone-x/).\n\nIf you notice anything amiss,\nlike a missing image\nor a page that isn't rendering as you expected,\nplease [let us know](https://github.com/nshipster/nshipster.com)!\n\n### Removed Site Search\n\nIn the process of upgrading the site's infrastructure,\nI ended up removing the search widget provided by\n[Swiftype](https://swiftype.com).\nI'm looking into a couple alternatives,\nbut don't currently have any specific plans for bringing site search back.\n\n### Retired Content\n\nTechnology evolves quickly.\nAnd while I've tried to write mostly evergreen content on NSHipster,\nthere are some articles that have become obsolete.\nFor example, our article about [BackRow](https://nshipster.com/backrow/)\nis irrelevant now that the tvOS is available.\n\nThese articles will live on in perpetuity at their original URLs,\nbut they'll include a deprecation notice at the top\nand won't be displayed in the main site navigation.\n\n## More Things to Look Forward To\n\nBut that's not all ---\nin addition to new weekly articles,\nwe have a lot of exciting things in the works:\n\n### CFHipsterRef Update and Print Edition\n\n[CFHipsterRef](https://gum.co/cfhipsterref)\nwas released\non the eve of Swift's announcement at WWDC 2014.\nAlthough this new language\ngets most of our attention these days\n(what, with its cool name and fast bird logo),\nObjective-C and low-level technologies\nare still just as important as ever.\n\nComing this fall,\nwe'll be releasing a second edition CFHipsterRef\nwith new and updated content.\nThis will be a free update to everyone who ordered the first edition.\n(I also look forward to finally making good on a promise I made\nto release a print edition of the book)\n\n### New Books\n\nI can't say too much yet,\nbut I'm planning to have a something out by the end of the year.\nStay tuned!\n\n> In the meantime,\n> check out [Flight School](https://flightdotschool.com).\n> It's a new, ongoing book series I'm working on\n> that's all about Swift.\n> Each book offers an in-depth look at essential topics\n> for intermediate and advanced developers.\n>\n> The first two books,\n> [Guide to Swift Codable](https://gumroad.com/l/codable)\n> and [Guide to Swift Numbers](https://gumroad.com/l/swift-numbers),\n> are both available for download,\n> with more on the way soon.\n\n### More Tools and Experiments\n\nNSHipster is more than writing blog posts and books.\nIt's also an opportunity to make fun and useful things\nfor the community.\n\nOne such project is\n[ASCIIwwdc](https://asciiwwdc.com),\na site that offers searchable transcripts of WWDC sessions\ngoing back to 2010.\nIt was recently updated with all of the sessions from 2017\nand most from 2018,\nso if you haven't gotten around to watching this year's talks,\nyou might find this to be a nice way to get up to speed quickly.\n\nAnother example is\n[SwiftDoc](https://swiftdoc.org).\nNate created this around the time that he took the reigns of NSHipster,\nand it's been an invaluable tool for understanding\nthe complex type relationships in the Swift standard library.\nI've updated the site for Swift 4.2,\nand look forward to keeping it in sync going forward.\n\nLook out for more of these in the future!\n\n### Conferences and Meetups Near You\n\nThis fall,\nI'll have the honor of presenting at\nsome of the best developer conferences of the year,\nin New York City, Logroño, Madrid, and Paris:\n\n- [try! Swift NYC](https://www.tryswift.co/events/2018/nyc/) • New York City, USA • September 4th & 5th\n- [NSSpain](https://2018.nsspain.com) • Logroño, Spain • September 12th – 14th\n- NSCoders Night • Madrid, Spain • September 11th\n- [FrenchKit](https://frenchkit.fr) • Paris, France • September 20th & 21st\n\nIf you plan on attending any of these\nor will be in any of these cities when I'm there,\n[please get in touch](https://twitter.com/mattt) (my DMs are open).\n\n---\n\nThank you to everyone who's supported NSHipster over the past 6 years.\nWe couldn't be more excited about what's to come.\n\nUntil next time:\nMay your code continue to compile and inspire.\n"
  },
  {
    "path": "sitemap.xml",
    "content": "---\nlayout: null\n---\n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\"\n    xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n    <url>\n        <loc>{{ site.url }}</loc>\n        <lastmod>{{ site.posts.first.date | date_to_xmlschema }}</lastmod>\n        <changefreq>daily</changefreq>\n        <priority>1.0</priority>\n    </url>\n\n  {% for post in site.posts %}\n    {% unless post.retired %}\n    <url>\n        <loc>{{ post.url | absolute_url }}</loc>\n        <lastmod>{{ post.updated_on | date_to_xmlschema }}</lastmod>\n        <changefreq>yearly</changefreq>\n        <priority>0.9</priority>\n    </url>\n    {% endunless %}\n  {% endfor %}\n\n  {% for author in site.authors %}\n    <url>\n        <loc>{{ author.url | absolute_url }}</loc>\n    </url>\n  {% endfor %}\n\n  {% for translator in site.translators %}\n    <url>\n        <loc>{{ translator.url | absolute_url }}</loc>\n    </url>\n  {% endfor %}\n</urlset>\n"
  },
  {
    "path": "status.md",
    "content": "---\nlayout: page\ntitle: Article Status\npermalink: /status\nretired: true\n---\n\nThe common swift (_Apus apus_) can travel at speeds over 100km/h.\nThe Swift programming language ---\ntrue to its name and namesake ---\nis similarly fast-moving,\nfrequently introducing new language features and syntax rules.\nAs a result,\nsome of our articles may become incorrect or outdated over time.\n\nWe do our best to keep things fresh,\nwith new updates to existing articles made every week,\nand invite you to help us find and correct any mistakes you find by\n[opening a new issue on our GitHub repository](https://github.com/NSHipster/articles/issues/new).\n\nIn the meantime,\nplease consult the table below\nfor guidance on when each of our articles was last updated,\nand which version of Swift it's targeting:\n\n<table id=\"status\">\n    <caption>\n        \"t.b.c.\" indicates that an article has not yet been translated to Swift<br/>\n        \"n/a\" notes that a Swift translation would not be useful or appropriate.\n    </caption>\n    <thead>\n        <tr>\n            <th>Article</th>\n            <th>Swift Version</th>\n            <th>Last Review</th>\n        </tr>\n    </thead>\n    <tbody>\n        {% assign sorted = site.posts | sort: 'title' %}\n        {% for post in sorted %}\n            <tr>\n                <td><a href=\"{{ post.url }}\">{{ post.title | camel_break }}</a></td>\n                <td class=\"version\">\n                    {% if post.status.swift == \"n/a\" %}\n                        <em>n/a</em>\n                    {% elsif post.status.swift == \"t.b.c.\" %}\n                        <strong>t.b.c.</strong>\n                    {% else %}\n                        {{ post.status.swift }}\n                    {% endif %}\n                </td>\n                <td>\n                    {% assign last_review = post.status.reviewed | default: post.date %}\n                    {% capture date_format %}{% t format.date %}{% endcapture %}\n                    {{ last_review | date: date_format }}\n                </td>\n            </tr>\n        {% endfor %}\n    </tbody>\n</table>\n"
  }
]