{% endif %}
{% endfor %}
================================================
FILE: _plugins/admonition-block.rb
================================================
# frozen_string_literal: true
module Jekyll
class AdmonitionBlock < Liquid::Block
def initialize(tag_name, arguments, tokens)
super
@type = tag_name
end
def render(context)
content = super
<<~EOD
EOD
end
end
end
%w[info warning error].each do |admonition|
Liquid::Template.register_tag(admonition, Jekyll::AdmonitionBlock)
end
================================================
FILE: _plugins/camel-case-thin-space-break-filter.rb
================================================
# frozen_string_literal: true
module Jekyll
module CamelCaseThinSpaceBreakFilter
REGEX = /(?:([a-z]{2,})([A-Z]+))/.freeze
def camel_break(string)
string.gsub(REGEX, "\\1\u200B\\2")
.gsub(/(mac|tv)\u200B(OS)/, "\\1\\2")
end
end
end
Liquid::Template.register_filter(Jekyll::CamelCaseThinSpaceBreakFilter)
================================================
FILE: _plugins/extended-date-filter.rb
================================================
# frozen_string_literal: true
require 'time'
module Jekyll
module ExtendedDateFilter
# Reformat a date using Ruby's core Time#strftime( string ) -> string
# with additional replacements.
#
# %a - The abbreviated weekday name (``Sun'')
# %A - The full weekday name (``Sunday'')
# %b - The abbreviated month name (``Jan'')
# %B - The full month name (``January'')
# %c - The preferred local date and time representation
# %d - Day of the month (01..31)
# %H - Hour of the day, 24-hour clock (00..23)
# %I - Hour of the day, 12-hour clock (01..12)
# %j - Day of the year (001..366)
# %m - Month of the year (01..12)
# %M - Minute of the hour (00..59)
# %o - Ordinal for the day of the month (st, nd, rd, th...)
# %p - Meridian indicator (``AM'' or ``PM'')
# %s - Number of seconds since 1970-01-01 00:00:00 UTC.
# %S - Second of the minute (00..60)
# %U - Week number of the current year,
# starting with the first Sunday as the first
# day of the first week (00..53)
# %W - Week number of the current year,
# starting with the first Monday as the first
# day of the first week (00..53)
# %w - Day of the week (Sunday is 0, 0..6)
# %x - Preferred representation for the date alone, no time
# %X - Preferred representation for the time alone, no date
# %y - Year without a century (00..99)
# %Y - Year with century
# %Z - Time zone name
# %% - Literal ``%'' character
#
# See also: http://www.ruby-doc.org/core/Time.html#method-i-strftime
def date(input, format)
return input unless date = datetime(input)
return input unless (format = format.to_s) && !format.empty?
date.strftime(format.gsub(/%o/, ordinal(date.day)))
end
private
def ordinal(number)
return 'th' if (11..13).cover?(number.to_i % 100)
case number.to_i % 10
when 1 then 'st'
when 2 then 'nd'
when 3 then 'rd'
else 'th'
end
end
def datetime(date)
case date
when String
Time.parse(date)
else
date
end
end
end
end
Liquid::Template.register_filter(Jekyll::ExtendedDateFilter)
================================================
FILE: _plugins/jwt-lexer.rb
================================================
# frozen_string_literal: true
require 'rouge'
module Rouge
module Lexers
class JWT < RegexLexer
tag 'jwt'
filenames '*.jwt'
title 'JSON Web Token (JWT)'
desc 'A compact URL-safe means of representing claims to be transferred between two parties.'
start { push :root }
state :root do
rule %r{^([A-Za-z0-9\-_=]+)(\.)([A-Za-z0-9\-_=]+)(\.?)([A-Za-z0-9\-_.+/=]*)$} do |m|
token Keyword, m[1]
token Punctuation, m[2]
token Literal::Number, m[1]
token Punctuation, m[4]
token Name::Variable, m[1]
end
end
end
end
end
================================================
FILE: _plugins/localization-filter.rb
================================================
# frozen_string_literal: true
require 'twitter_cldr'
module Jekyll
module LocalizationFilter
def as_language_code(input, locale = nil)
return '中文' if input == 'zh-Hans' && locale == 'zh-Hans'
code = TwitterCldr.convert_locale(input)
TwitterCldr::Shared::Languages.from_code_for_locale(code, locale || :en)
end
def to_sentence(list)
formatter = TwitterCldr::Formatters::ListFormatter.new(current_locale.language)
formatter.format(list.map(&:strip).reject(&:empty?))
end
private
def current_locale
# TwitterCldr.convert_locale(Jekyll.sites.first.config['lang'])
TwitterCldr::Shared::Locale.parse(Jekyll.sites.first.config['lang']).maximize
end
end
end
Liquid::Template.register_filter(Jekyll::LocalizationFilter)
================================================
FILE: _plugins/markdown-converter.rb
================================================
# frozen_string_literal: true
require 'yaml'
require 'jekyll'
require 'nokogiri'
require 'active_support/inflector'
module Jekyll
module Converters
class Markdown
# :nodoc:
class NSHipsterProcessor
def initialize(config)
@kramdown = KramdownParser.new(config)
end
def convert(content)
cache.getset(content) do
content.gsub!('<#...#>', "\uFFFC")
html = @kramdown.convert(content)
doc = Nokogiri::HTML::DocumentFragment.parse(html)
remove_proprietary_attributes!(doc)
secure_links_to_cross_origin_destinations!(doc)
transform_apple_trademarks!(doc)
transform_code_symbols!(doc)
transform_placeholder_tokens!(doc)
add_heading_anchors!(doc)
unnest_code_listing_markup!(doc)
consolidate_consecutive_code_listings!(doc)
improve_accessibility!(doc)
style_optional_placeholders!(doc)
delineate_flim_flam!(doc)
doc.to_html.gsub("\uFFFC", '…')
end
end
private
def cache
@@cache ||= Jekyll::Cache.new('ConvertMarkdown')
end
def remove_proprietary_attributes!(doc)
doc.css('[markdown]').each do |element|
element.remove_attribute('markdown')
end
end
def transform_code_symbols!(doc)
doc.css(':not(pre) code').each do |code|
code.remove_attribute('class')
code.inner_html = code.inner_html.gsub(/(?:([a-z])([A-Z]+))/, '\\1\\2')
end
end
def transform_apple_trademarks!(doc)
doc.css('p, li, td').each do |p|
p.inner_html = p.inner_html.gsub(/iPhone X([SR])/, 'iPhone X\\1')
end
end
def secure_links_to_cross_origin_destinations!(doc)
doc.css('a[href]').each do |a|
href = a.attr('href')
next if href =~ %r{^/|#{ENV['DOMAIN']}}
a['rel'] = 'noopener noreferrer'
end
end
def transform_placeholder_tokens!(doc)
doc.css('code').each do |code|
code.inner_html = code.inner_html.gsub(/<#\s*(.*?)\s*#>/, '\\1')
end
end
def add_heading_anchors!(doc)
selector = (1..6).map { |n| "h#{n}" }.join(', ')
doc.css(selector).each do |h|
next unless id = h.attr('id')
id = ActiveSupport::Inflector.parameterize(id)
h.remove_attribute('id')
h.prepend_child(%())
end
end
def unnest_code_listing_markup!(doc)
doc.css('div.highlighter-rouge').each do |div|
class_name = div.classes.detect { |c| !c.match?(/rouge/) }
language = case class_name
when /swift/ then 'Swift'
when /objc|objective-c/ then 'Objective-C'
when /json-ld/ then 'JSON-LD'
when /json/ then 'JSON'
when /python/ then 'Python'
when /ruby/ then 'Ruby'
when /javascript/ then 'JavaScript'
when /terminal/ then 'Terminal'
when /html/ then 'HTML'
when /xml/ then 'XML'
when /jwt/ then 'JWT'
when /applescript/ then 'AppleScript'
when /lisp/ then 'Lisp'
when /fortran/ then 'FORTRAN'
when /cobol/ then 'COBOL'
when /xcconfig/ then 'Xcode Build Settings'
when /turtle/ then 'Turtle'
when /sparql/ then 'SPARQL'
when /sql/ then 'SQL'
when /cypher/ then 'Cypher'
when /ntriples/ then 'N-Triples'
when nil then ''
else
class_name.gsub(/language-/, '')
end
pre = div.at('pre')
pre['class'] = 'highlight'
pre['data-lang'] = language
div.swap(pre)
end
end
def consolidate_consecutive_code_listings!(doc)
doc.css('pre.highlight').each do |pre|
next if pre.parent['class'] == 'highlight-group'
group = pre.wrap(%(
)).parent
while sibling = group.at_xpath('following-sibling::node()[not(self::text()[not(normalize-space())])][1]')
break unless sibling.classes.include?('highlight')
group.add_child(sibling)
end
group.swap(group.child) if group.children.count == 1
end
number = 1
doc.css('div.highlight-group').each do |group|
group.prepend_child('')
tablist = group.at('[role="tablist"]')
group.css('pre.highlight').each_with_index do |div, index|
language = div['data-lang'] || 'text'
id = "code-listing-#{number}-#{language.downcase}"
div['id'] = id.to_s
div['role'] = 'tabpanel'
div['tabindex'] = '0'
div['aria-labelledby'] = "#{id}-tab"
div['hidden'] = 'hidden' unless index == 0
tablist.add_child(%(
))
end
number += 1
end
end
def improve_accessibility!(doc)
doc.css('img[src$=".svg"]').each do |img|
img['role'] = 'img'
end
doc.css('img:not([alt])').each do |img|
img['alt'] = ''
end
end
def style_optional_placeholders!(doc)
doc.css('var.placeholder').each do |var|
next unless var.text.match?(/[\[\]]/)
var.add_class('optional')
var['title'] = 'Optional'
var.inner_html = var.inner_html.gsub(/[\[\]]/, '')
end
end
def delineate_flim_flam!(doc)
if divider = (doc.at_css('hr') || doc.at_css('h2'))
divider.add_next_sibling(%())
end
end
end
end
end
end
================================================
FILE: _plugins/page-translation-hook.rb
================================================
# frozen_string_literal: true
Jekyll::Hooks.register :pages, :pre_render do |page|
page.data['translations'] = page.site.config['domains'].keys if page.index?
end
================================================
FILE: _plugins/post-commit-history-hook.rb
================================================
# frozen_string_literal: true
require 'uri'
Jekyll::Hooks.register :posts, :pre_render do |post|
language = post.site.config['lang']
repository_name = case language
when /^en/ then 'articles'
when /^es/ then 'articles-es'
when /^fr/ then 'articles-fr'
when /^ko/ then 'articles-ko'
when /^zh-Hans/ then 'articles-zh-Hans'
when /^ru/ then 'articles-ru'
when nil
raise 'Unspecified language in site configuration'
else
raise "Unknown language: #{language}"
end
filename = File.basename(post.path)
post.data['commit_history_url'] = "https://github.com/nshipster/#{repository_name}/commits/master/#{filename}"
end
================================================
FILE: _plugins/post-revisions-hook.rb
================================================
# frozen_string_literal: true
require 'date'
Jekyll::Hooks.register :posts, :pre_render do |post|
if post.data['revisions']
latest_revision = post.data['revisions'].keys.max
raise unless latest_revision && (last_revised_on = Time.parse("#{latest_revision}"))
post.data['revision_description'] = post.data['revisions'][latest_revision]
post.data['last_revised_on'] = last_revised_on
post.data['updated_on'] = last_revised_on
else
post.data['updated_on'] = post.date
end
end
================================================
FILE: _plugins/post-translation-hook.rb
================================================
# frozen_string_literal: true
Jekyll::Hooks.register :posts, :pre_render do |post|
directory = File.expand_path('../../..', post.path)
filename = File.basename(post.path)
slug = filename.sub(/\A\d{4}-\d{,2}-\d{,2}-/, '')
translations = Dir["#{directory}/**/*#{slug}"].reject { |f| f == post.path }
post.data['translations'] = []
translations.each do |translation|
next unless language = File.expand_path('../..', translation).split('/').last
post.data['translations'] << language
end
end
================================================
FILE: _plugins/search-index-generator.rb
================================================
# frozen_string_literal: true
module Jekyll
class SearchIndexGenerator < Generator
priority :low
def generate(site)
index = site.posts.docs.reverse
.filter { |post| !post.data['retired'] }
.map do |post|
{
url: site.config['url'] + post.url,
title: post.data['title'],
category: post.data['category'],
content: post.data['excerpt']
}
end
File.open('_functions/search/index.json', 'w') do |f|
f.puts index.to_json
end
end
end
end
================================================
FILE: _plugins/shuffle-filter.rb
================================================
# frozen_string_literal: true
module Jekyll
module ShuffleFilter
def shuffle(input = [])
input.sort_by { rand }
rescue StandardError
input
end
end
end
Liquid::Template.register_filter(Jekyll::ShuffleFilter)
================================================
FILE: _plugins/translate-tag.rb
================================================
# frozen_string_literal: true
module Jekyll
class Site
attr_accessor :translations
end
class TranslateTag < Liquid::Tag
def initialize(tag_name, key, tokens)
super
@key = key.strip
end
def render(context)
key = key(context)
translation = translations(context).dig(*key.split('.'))
if translation.nil? || translation.empty?
raise "Missing i18n key: #{lang}: #{key}"
end
translation
end
private
def key(context)
key = if context[@key].to_s != ''
context[@key].to_s
else
@key
end
key = Liquid::Template.parse(key).render(context)
raise "Invalid key #{key}" unless key.is_a?(String)
key
end
def translations(context)
site = context.registers[:site]
site.translations ||= {}
lang = site.config['lang']
unless site.translations.key?(lang)
puts "Loading translations from #{site.source}/_i18n/#{lang}.yml"
site.translations[lang] = YAML.load_file("#{site.source}/_i18n/#{lang}.yml")
end
site.translations[lang]
end
end
end
Liquid::Template.register_tag('t', Jekyll::TranslateTag)
Liquid::Template.register_tag('translate', Jekyll::TranslateTag)
================================================
FILE: _plugins/unwrap-filter.rb
================================================
# frozen_string_literal: true
require 'nokogiri'
module Jekyll
module UnwrapFilter
def unwrap(input)
return '' if input.nil? || input.empty?
fragment = Nokogiri::HTML::DocumentFragment.parse(input)
fragment.children.map(&:inner_html).join(' ')
end
end
end
Liquid::Template.register_filter(Jekyll::UnwrapFilter)
================================================
FILE: _plugins/url-filter.rb
================================================
# frozen_string_literal: true
require 'uri'
module Jekyll
module URLFilter
def host(input)
return input unless uri = URI(input)
uri.host
end
end
end
Liquid::Template.register_filter(Jekyll::URLFilter)
================================================
FILE: _plugins/well-known-hook.rb
================================================
# frozen_string_literal: true
require 'fileutils'
Jekyll::Hooks.register :site, :post_write do |site|
site.static_files.select do |f|
next unless f.relative_path.include?('.well-known')
FileUtils.cp(f.path, site.dest)
end
end
================================================
FILE: assets/css/_admonitions.scss
================================================
@mixin border-icon($name) {
content: " ";
background-image: asset_url($name + ".svg");
background-size: 24px 24px;
width: 24px;
height: 24px;
position: absolute;
display: block;
margin-left: -54px;
margin-top: 10px;
z-index: 100;
}
.admonition {
--code: var(--link);
font-family: $sans-serif-font-stack;
border-left: 4px var(--separator) solid;
padding: 5px 40px;
margin: 1.5em 0;
display: block;
clear: both;
overflow: visible;
font-size: smaller;
a {
text-decoration: underline;
}
p {
margin: 0.5em 0;
}
dl {
padding: 0.5em 0 !important;
margin-bottom: 1em !important;
}
pre code {
font-size: small;
line-height: 1;
}
th,
td {
padding: 0.5em !important;
}
blockquote {
margin-left: 0 !important;
margin-top: 0.25em !important;
margin-bottom: 0.25em !important;
border-left-color: var(--separator) !important;
}
ins {
background: transparent !important;
}
&.info {
--link: var(--blue);
--separator: var(--blue);
--background: #edf5fa;
&:before {
@include border-icon("info");
}
}
&.warning {
--background: #fcfaf6;
--separator: var(--yellow);
--link: rgb(178, 129, 6);
&:before {
@include border-icon("warning");
}
}
&.error {
--background: #fcf2f6;
--link: var(--pink);
--separator: var(--pink);
&:before {
@include border-icon("error");
}
}
}
================================================
FILE: assets/css/_animations.scss
================================================
@keyframes twirl {
0% {
transform: scale(1) rotate(0);
}
10%,
20% {
transform: scale(0.9) rotate(-3deg);
}
30%,
50%,
70%,
90% {
transform: scale(1.1) rotate(3deg);
}
40%,
60%,
80% {
transform: scale(1.1) rotate(-3deg);
}
100% {
transform: scale(1) rotate(0);
}
}
================================================
FILE: assets/css/_code.scss
================================================
pre.highlight {
background: var(--secondary-background);
border: 1px var(--separator-opaque) solid;
border-radius: 4px;
overflow: auto;
padding: 0.5em 1em;
margin-bottom: 1em;
code {
color: var(--text);
background: transparent !important;
}
&[data-lang="JWT"] {
white-space: pre-wrap;
}
}
.highlight {
.placeholder {
color: var(--text);
}
.o {
color: var(--text);
}
.p {
color: var(--gray);
}
.err {
color: var(--gray);
}
.s,
.sa,
.sb,
.sc,
.dl,
.sd,
.s2,
.sh,
.sx,
.sr,
.s1,
.ss {
color: var(--orange);
}
.se,
.si {
color: var(--text);
}
.k,
.kc,
.kd,
.kn,
.kp,
.kr {
color: var(--purple);
}
.kt {
color: var(--text);
}
.kd + .kt {
color: var(--text);
}
.go,
.nc,
.nf,
.nv {
color: var(--text);
}
.kt + .o + .n,
.nf {
color: var(--indigo);
}
.cp,
.c1 {
color: var(--gray);
}
.n,
.na,
.nb,
.bp,
.no,
.nd,
.ni,
.py,
.nl,
.nn,
.nx,
.nt,
.vc,
.vg,
.vi {
color: var(--text);
}
.l,
.ld,
.s,
.sb,
.sc,
.sd,
.s2,
.se,
.sh,
.si,
.sx,
.sr,
.s1,
.ss,
.m,
.mf,
.mh,
.mi,
.il,
.mo,
.mx,
.mb {
color: var(--indigo);
}
}
@media (prefers-color-scheme: dark) {
.highlight {
.p {
color: var(--gray2);
}
.err {
color: var(--gray);
}
.s,
.sa,
.sb,
.sc,
.dl,
.sd,
.s2,
.sh,
.sx,
.sr,
.s1,
.ss {
color: var(--green);
}
.se,
.si {
color: var(--text);
}
.k,
.kc,
.kd,
.kn,
.kp,
.kr {
color: var(--teal);
}
.kt {
color: var(--yellow);
}
.kd + .kt {
color: var(--orange);
}
.go,
.nc,
.nf,
.nv {
color: var(--text);
}
.kt + .o + .n,
.nf {
color: var(--purple);
}
.cp {
color: var(--red);
}
.c1 {
color: var(--gray2);
}
.n + .o + .n,
.na,
.nb,
.bp,
.no,
.nd,
.ni,
.py,
.nl,
.nn,
.nx,
.nt,
.vc,
.vg,
.vi {
color: var(--pink);
}
.l,
.ld,
.s,
.sb,
.sc,
.sd,
.s2,
.se,
.sh,
.si,
.sx,
.sr,
.s1,
.ss,
.m,
.mf,
.mh,
.mi,
.il,
.mo,
.mx,
.mb {
color: var(--orange);
}
}
}
================================================
FILE: assets/css/_colors.scss
================================================
:root {
--red: rgb(255, 59, 48);
--orange: rgb(255, 128, 0);
--yellow: rgb(255, 204, 0);
--green: rgb(52, 199, 89);
--teal: rgb(90, 200, 250);
--blue: rgb(0, 122, 255);
--indigo: rgb(88, 86, 214);
--purple: rgb(175, 82, 222);
--pink: rgb(255, 45, 85);
--gray: rgb(142, 142, 147);
--gray2: rgb(174, 174, 178);
--gray3: rgb(199, 199, 204);
--gray4: rgb(209, 209, 214);
--gray5: rgb(229, 229, 234);
--gray6: rgb(242, 242, 247);
--text: rgb(0, 0, 0);
--secondary-text: rgb(60, 60, 67);
--placeholder-text: rgb(60, 60, 67);
--code: var(--purple);
--link: var(--orange);
--separator: rgb(60, 60, 67);
--opaque-separator: rgb(198, 198, 200);
--fill: rgb(120, 120, 128);
--secondary-fill: rgb(120, 120, 128);
--background: rgb(242, 242, 247);
--secondary-background: rgb(255, 255, 255);
}
@supports (color: color(display-p3 1 1 1)) {
* {
transition: none !important;
}
:root {
--red: color(display-p3 1 0.2314 0.1882);
--orange: color(display-p3 1 0.5 0);
--yellow: color(display-p3 1 0.8 0);
--green: color(display-p3 0.2039 0.7804 0.349);
--teal: color(display-p3 0.3529 0.7843 0.9804);
--blue: color(display-p3 0 0.4784 1);
--indigo: color(display-p3 0.3451 0.3373 0.8392);
--purple: color(display-p3 0.6863 0.3216 0.8706);
--pink: color(display-p3 1 0.1765 0.3333);
--gray: color(display-p3 0.5569 0.5569 0.5765);
--gray2: color(display-p3 0.6824 0.6824 0.698);
--gray3: color(display-p3 0.7804 0.7804 0.8);
--gray4: color(display-p3 0.8196 0.8196 0.8392);
--gray5: color(display-p3 0.898 0.898 0.9176);
--gray6: color(display-p3 0.949 0.949 0.9686);
--text: color(display-p3 0 0 0);
--secondary-text: color(display-p3 0.2353 0.2353 0.2627);
--placeholder-text: color(display-p3 0.2353 0.2353 0.2627);
--separator: color(display-p3 0.2353 0.2353 0.2627);
--opaque-separator: color(display-p3 0.7765 0.7765 0.7843);
--fill: color(display-p3 0.4706 0.4706 0.502);
--secondary-fill: color(display-p3 0.4706 0.4706 0.502);
--background: color(display-p3 0.949 0.949 0.9686);
--secondary-background: color(display-p3 1 1 1);
}
}
html {
border-top: 3px var(--orange) solid;
body {
background-color: var(--background);
color: var(--text);
}
}
#logo {
#ns {
fill: var(--orange);
}
}
================================================
FILE: assets/css/_functions.scss
================================================
@mixin clearfix {
&:after {
content: " ";
display: block;
clear: both;
}
}
@mixin disable-selection {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
}
================================================
FILE: assets/css/_inputs.scss
================================================
button,
input[type="submit"] {
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
-webkit-appearance: none;
-webkit-font-smoothing: antialiased;
appearance: none;
background-color: var(--orange);
border-radius: 4px;
border: none;
color: white;
cursor: pointer;
display: inline-block;
font-size: 1em;
font-weight: bold;
line-height: 1;
padding: 0.75em 1em;
text-decoration: none;
transition: background-color 0.25s;
user-select: none;
vertical-align: middle;
white-space: nowrap;
}
button:hover,
input[type="submit"]:hover {
color: white;
}
================================================
FILE: assets/css/_layout.scss
================================================
@import "functions";
html,
body {
margin: 0;
}
body {
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
border-top: 3px var(--orange) solid;
}
hr {
border: none;
margin: 1em 0;
padding: 1em 0;
display: block;
}
img {
margin: 0;
max-width: 100%;
}
video {
margin: 0 auto;
max-width: 100%;
display: block;
}
blockquote {
border-left: 2px solid var(--separator);
color: var(--secondary-text);
margin: 1.5em 0;
padding-left: 0.75em;
}
cite {
color: var(--text);
font-style: italic;
&:before {
content: "— ";
}
}
table {
border-collapse: collapse;
margin: 0.75em 0;
table-layout: fixed;
width: 100%;
}
thead th {
border-bottom: 1px solid var(--separator-opaque);
font-weight: bold;
padding: 0.75em 0;
text-align: left;
}
tbody td {
border-bottom: 1px solid var(--separator);
padding: 0.75em 0;
}
tbody tr:last-of-type td {
border-bottom: none;
}
tr,
td,
th {
vertical-align: middle;
}
ul,
ol {
margin: 0;
padding: 0;
list-style-type: none;
}
dl {
margin-bottom: 0.75em;
dt {
font-weight: bold;
margin: 1em 0;
}
dd {
margin: 0 0 0.25rem 1em;
}
}
.container {
@include clearfix;
max-width: 100%;
margin-left: auto;
margin-right: auto;
max-width: 960px;
margin: 0 auto;
padding: 2em;
section {
@include clearfix;
display: block;
max-width: 100%;
margin-left: auto;
margin-right: auto;
margin-bottom: 2em;
padding-bottom: 1em;
}
}
html[lang="fr-FR"] [role="banner"] {
#logo {
margin-right: 5.5em;
}
.tagline {
font-size: 1.25em;
}
}
html[lang="zh-Hans"] [role="banner"] {
#logo {
margin-right: 9.5em;
}
.tagline {
font-size: 1.4em;
padding-bottom: 1em;
}
}
html[lang="ko-KR"] [role="banner"] {
.tagline {
font-size: 1.25em;
}
}
[role="banner"] {
display: flex;
margin-bottom: 1.5em;
padding-bottom: 1.5em;
#logo {
display: block;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 1em;
height: 6em;
margin: 0.25em 6em 0 0;
a {
display: block;
}
svg {
width: 146px;
height: 84px;
overflow: visible;
margin-left: -3px;
#mustache {
position: absolute;
transform: rotate(0) scale(1);
transform-origin: 50% 70% 0;
transition: transform 1s;
}
&:hover,
&.animated {
position: relative;
z-index: 2;
#mustache {
animation: twirl 1s ease-in-out;
}
}
}
}
.tagline {
flex: 1;
}
}
#latest,
#announcement {
h1 {
margin-bottom: 0.5rem;
}
}
#announcement {
background-color: rgba(255, 128, 0, 0.2);
margin-left: -1em;
margin-right: -1em;
padding: 1em;
}
#recent {
ul {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1em 2em;
li {
min-height: 15em;
.title {
height: 4em;
font-size: 1.75em;
display: table-cell;
line-height: 1;
vertical-align: bottom;
padding-bottom: 1em;
}
p {
font-size: smaller;
display: -webkit-box;
overflow: hidden;
max-lines: 8;
-webkit-line-clamp: 8;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}
}
}
}
#merchandise {
margin-top: -30px;
h1 {
margin-bottom: 15px;
}
}
article.author,
article.translator {
padding-top: 2em;
header {
display: grid;
grid-template:
"avatar . title"
"avatar . description";
grid-template-columns: 1fr 1em 3fr;
grid-template-rows: 1fr 2fr;
gap: 1em 1em;
margin-bottom: 1em;
padding-bottom: 1em;
.avatar {
grid-area: avatar;
}
h1 {
grid-area: title;
}
p {
grid-area: description;
}
}
}
[role="article"] {
margin-bottom: 1em;
overflow-x: hidden;
table {
overflow: scroll;
-webkit-overflow-scrolling: touch;
margin: 2em 0;
caption {
margin: 2em 0 1em 0;
}
}
header {
display: block;
text-align: center;
margin-bottom: 3em;
.byline {
font-family: $serif-font-stack;
font-style: italic;
font-weight: 300;
color: var(--secondary-text);
a,
span,
time {
white-space: nowrap;
}
.authors,
.translators {
&:after {
content: " — ";
}
}
}
}
.content {
margin-bottom: 4em;
h1,
h2,
h3,
h4,
h5 {
margin-top: 2.5rem;
}
object,
embed,
figure,
svg {
margin: 1em auto;
display: block;
width: auto;
}
img {
margin: 1em auto;
display: block;
}
ul,
ol {
margin: 1.5em 0;
padding: 0 3em;
ul,
ol {
margin-top: 0.5em;
}
li {
list-style: disc;
}
}
figure {
text-align: center;
margin: 1em 0;
padding: 1em 0;
}
ins {
background-color: rgba(255, 128, 0, 0.2);
text-decoration: none;
}
dl {
padding: 1em 0;
}
blockquote {
margin: 2em;
margin-right: 4em;
border-left: 3px var(--orange) solid;
cite {
margin-top: 1em;
display: block;
}
}
table {
thead th {
text-align: center;
}
td {
padding: 1em;
}
table {
margin: 0;
th,
td {
border: none;
padding: 0.25em;
}
}
}
}
sup {
font-size: 50%;
time & {
margin-right: -0.5em;
}
}
footer {
.contributor {
float: left;
display: block;
margin-right: 2.35765%;
width: 48.82117%;
padding: 1em 0;
&:last-child,
&:nth-child(2n) {
margin-right: 0;
}
&:nth-child(2n + 1) {
clear: left;
}
&:only-child {
width: 100%;
.avatar {
padding: 0 1em;
}
}
.avatar {
float: left;
display: block;
margin-right: 4.82916%;
width: 30.11389%;
&:last-child {
margin-right: 0;
}
}
.details {
float: left;
display: block;
margin-right: 4.82916%;
width: 65.05695%;
margin-right: 0;
margin-top: 1em;
&:last-child {
margin-right: 0;
}
span {
font-weight: 700;
}
p {
font-size: 0.75em;
margin-top: 1em;
}
}
}
small {
display: block;
font-size: 1em;
font-weight: 700;
color: var(--secondary-text);
text-transform: lowercase;
font-family: $sans-serif-font-stack;
font-variant: small-caps;
margin-bottom: 1em;
}
}
}
[role="complementary"] {
border-top: 1px #ddd solid;
padding-top: 2em;
}
[role="contentinfo"] {
text-align: center;
margin-top: 2em;
padding: 1em;
section {
margin-bottom: 0;
padding-bottom: 0;
}
}
.avatar {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
max-width: 200px;
max-height: 200px;
border-radius: 50%;
pointer-events: none;
user-select: none;
}
#contributors {
ul {
display: flex;
justify-content: center;
align-content: space-between;
flex-flow: row wrap;
li {
flex: 0;
display: block;
margin-bottom: 1em;
flex-basis: 15%;
padding: 0.25em;
.avatar {
width: 75%;
display: block;
margin: 0 auto 1em auto;
}
a {
text-align: center;
display: block;
font-size: small;
}
}
}
}
.archive {
dl {
float: left;
display: block;
margin-right: 2.5%;
width: 30%;
&:last-child,
&:nth-of-type(3),
&:nth-of-type(4),
&:nth-of-type(6) {
margin-right: 0;
}
}
ol,
ul {
list-style: none;
li {
margin: 2em 0;
}
span,
time {
display: block;
}
time {
white-space: nowrap;
font-style: italic;
font-weight: 300;
margin-bottom: 1em;
}
}
}
#publications {
.books {
display: flex;
}
.book {
flex: 1;
img {
display: block;
margin: 0 auto;
width: 200px;
border: 4px transparent solid;
transition: 0.25s ease-in-out border-color;
filter: none !important;
&:hover {
padding: 0;
border: 4px var(--orange) solid;
}
}
}
}
.tagline {
clear: both;
font-weight: 300;
}
.highlight-group {
margin-top: 1em;
}
[role="tablist"] {
display: flex;
flex-direction: row;
justify-content: flex-end;
padding-right: 3px;
button {
cursor: pointer;
flex: 0;
padding-left: 0.5em;
color: var(--fill) !important;
text-decoration: none;
transition: opacity 0.5s;
background: transparent !important;
padding: 0;
margin: 0 0 0 0.5em;
&:not([aria-selected="true"]) {
opacity: 0.25;
&:hover {
opacity: 0.5;
}
}
&.active {
opacity: 1;
}
&:focus {
outline: thin dotted;
outline-offset: 2px;
}
}
}
[role="tabpanel"] {
margin-top: 0.25em;
&:focus {
outline: 0;
}
}
#promotion {
article {
background-color: rgba(255, 128, 0, 0.2);
background-color: color(p3 1 0.5 0 0.2);
margin-left: -1em;
margin-right: -1em;
margin-top: 0.5em;
padding: 1.5em 1em;
}
.book {
@include disable-selection;
float: left;
width: 500px;
margin-left: -150px;
margin-top: -150px;
margin-right: -20px;
img {
margin: 0;
margin-top: 100px;
}
}
& > small {
font-style: italic;
}
h3 {
font-family: $serif-font-stack;
font-size: 1.25em;
margin-bottom: 0.5em;
a {
color: inherit;
}
}
h4 {
font-family: $serif-font-stack;
font-style: italic;
font-weight: 300;
margin-bottom: 1em;
sup {
vertical-align: baseline;
font-size: 1;
}
}
p {
font-size: 0.75em;
}
a.buy {
background: var(--orange);
border-radius: 10px;
color: white !important;
font-family: $sans-serif-font-stack;
font-weight: 700;
margin-top: 1em;
padding: 0.5em 1.5em;
text-align: center;
display: inline-block;
&:hover {
text-decoration: none !important;
}
}
.price {
cursor: help;
display: block;
text-align: right;
float: right;
padding-left: 1em;
* {
display: block;
}
del {
font-size: smaller;
}
ins {
text-decoration: none;
font-size: larger;
}
}
}
table#status {
table-layout: fixed;
margin-top: 2em;
caption {
padding: 1em 0;
color: var(--secondary-text);
}
.version {
text-align: center;
em {
color: var(--secondary-text);
}
}
}
table#customplaygrounddisplayconvertible-categories {
table-layout: auto;
tbody th {
padding-left: 10px;
text-align: center;
}
ul {
padding: 0 0 0 20px;
li {
margin: 0;
}
}
td img {
margin: 0;
}
}
@media screen and (max-width: 600px) {
table#customplaygrounddisplayconvertible-categories {
thead tr th:last-child,
tbody tr td:last-child {
display: none;
}
}
}
details {
summary {
cursor: pointer;
margin-bottom: 1em;
user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
}
#translations {
font-size: smaller;
dt,
dd {
font-weight: 300 !important;
display: inline;
margin: 0;
font-display: optional;
font-style: normal;
}
}
[hidden] {
display: none !important;
}
================================================
FILE: assets/css/_typography.scss
================================================
@import "fonts/merriweather";
@import "fonts/batang";
@import "fonts/cc";
@import "colors";
$serif-font-stack: "Merriweather", Georgia, serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
$sans-serif-font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
$mono-font-stack: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
monospace;
html,
body {
font-family: $serif-font-stack;
font-size: 16pt;
line-height: 21pt;
font-weight: 300;
font-kerning: normal;
-webkit-font-kerning: normal;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html[lang="ko-KR"] {
body {
font-family: "Batang", $serif-font-stack;
font-weight: lighter;
}
}
html[lang="ko-KR"],
html[lang="zh-Hans"] {
a.readmore,
section > h1,
article p em,
article p dfn,
cite {
font-style: normal;
font-weight: bold;
}
[role="article"] header .byline {
font-style: normal;
}
.archive {
ol li time,
ul li time {
font-style: normal;
font-weight: bold;
}
}
#promotion h4 {
font-style: normal;
font-weight: bold;
}
.highlight span {
font-style: normal !important;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: $sans-serif-font-stack;
line-height: 1.1em;
margin: 0 0 1rem 0;
small {
display: block;
font-size: small;
font-variant: small-caps;
text-transform: uppercase;
font-weight: normal;
line-height: 2;
letter-spacing: 0.2ch;
}
em {
font-style: normal;
}
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.5em;
}
h4 {
font-size: 1.25em;
}
h5 {
font-size: 1.125em;
}
h6 {
font-size: 1em;
}
p {
margin: 0 0 1rem 0;
}
a {
transition: color 0.1s linear;
text-decoration: none;
&,
&:visited {
color: var(--link);
}
&:hover {
text-decoration: underline;
}
&:active,
&:focus {
outline: none;
}
code {
white-space: nowrap;
text-decoration: underline;
}
}
p > small {
font-size: inherit;
font-variant: small-caps;
text-transform: lowercase;
}
:not(pre) > code {
user-select: all;
}
:matches(a, p, li, dd, td) {
code {
padding: 0.25em;
font-size: smaller;
border-radius: 4px;
}
}
:matches(p, li, dd, td) {
code {
color: var(--code);
}
}
ol,
ul {
li {
margin-bottom: 0.5em;
}
}
pre {
font-family: $serif-font-stack;
}
code,
samp {
font-family: $mono-font-stack;
}
pre code,
samp {
font-size: smaller;
line-height: 1.1em;
}
samp {
white-space: pre;
overflow: scroll;
-webkit-overflow-scrolling: touch;
display: block;
padding: 0.5em 0;
}
section > h1 {
font-family: $serif-font-stack;
font-weight: 300;
font-size: 1.5em;
text-align: center;
margin-bottom: 2rem;
margin-top: 2rem;
}
article.excerpt h1 {
font-size: 1.5em;
}
a.readmore {
font-style: italic;
}
kbd {
border-radius: 4px;
border: 1px var(--separator) solid;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #fff inset;
font-family: $sans-serif-font-stack;
font-variant: small-caps;
margin: 0 0.1em;
padding: 0.1em 0.6em;
text-transform: lowercase;
}
abbr,
.small-caps {
font-variant: small-caps;
text-transform: lowercase;
}
.placeholder {
color: var(--placeholder-text);
display: inline-block;
padding: 0.25em;
border: 1px var(--opaque-separator) solid;
border-radius: 4px;
font-style: normal;
&.optional {
opacity: 0.5;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
&:hover .anchor::before {
opacity: 1;
}
}
.title {
font-family: $sans-serif-font-stack;
font-weight: 700;
}
.anchor::before {
content: "#";
opacity: 0;
transition: 300ms opacity;
position: absolute;
float: left;
margin-left: -1.5em;
padding: 0 0.5em;
color: var(--secondary-text) !important;
text-decoration: none;
:focus {
outline: none;
}
}
.tagline {
font-size: 1.33em;
}
#latest,
#announcement {
small {
font-style: italic;
}
}
[role="article"] {
header {
h1 {
font-size: 3.5em;
line-height: 1;
margin-bottom: 0.5rem;
padding: 0.5rem 0;
}
}
}
#archive {
dd {
font-size: smaller;
display: list-item;
list-style: circle;
}
}
.nowrap {
white-space: nowrap;
}
[lang*="-fonipa"] {
font-family: $sans-serif-font-stack;
font-weight: normal;
font-style: normal;
}
[lang*="-Zsye"] {
font-style: normal !important;
}
figcaption {
font-style: italic;
font-size: smaller;
}
table * {
font-feature-settings: "tnum";
}
aside.parenthetical {
font-size: smaller;
font-style: italic;
color: var(--secondary-text);
padding-bottom: 1em;
p:before {
content: "(";
}
p:after {
content: ")";
}
a,
code {
color: var(--secondary-text) !important;
background: transparent !important;
}
a {
text-decoration: underline;
}
}
li aside.parenthetical {
display: inline-block;
padding-bottom: 0;
p {
margin-bottom: 0;
}
}
.bibliography {
font-size: smaller;
}
del {
opacity: 0.5;
}
[role="contentinfo"] i {
font-family: "Creative Commons Symbols";
font-style: normal;
}
================================================
FILE: assets/css/articles/1password-cli.scss
================================================
figure#create-vault-dialog {
display: block;
width: 360px !important;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin: 0 auto;
display: block;
padding: 10px;
background-color: #fff;
border: 1px solid #ccc;
}
@media (prefers-color-scheme: dark) {
figure#create-vault-dialog {
border-color: #777;
background-color: #262626;
}
}
span.field {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
border: 1px solid #0370eb;
padding: 0.1rem 0.2rem;
border-radius: 0.2rem;
}
div.fields {
margin-top: 0.5rem;
font-size: 0.8rem;
}
figure#authorization-modal {
display: block;
width: 360px !important;
margin: 0 auto;
}
.highlight {
.gd {
background-color: rgba(255, 59, 48, 0.5);
}
.gi {
background-color: rgba(52, 199, 89, 0.5);
}
}
================================================
FILE: assets/css/articles/as-we-may-code.scss
================================================
.nohighlight * {
color: var(--gray) !important;
}
p > code {
.kd {
color: var(--teal);
}
.nf {
color: var(--purple);
}
.p {
color: var(--gray);
}
}
================================================
FILE: assets/css/articles/availability.scss
================================================
figure#wavailability {
table {
table-layout: auto;
font-size: smaller;
td[colspan="7"] {
text-align: left;
}
table {
td {
padding: 0.5em;
border-bottom: 1px solid #b7b7b7;
}
tr:last-of-type td {
border: none;
}
}
}
}
================================================
FILE: assets/css/articles/caemitterlayer.scss
================================================
#webgl-confetti {
position: relative;
width: 500px;
margin: 1em auto;
display: block;
canvas {
position: absolute;
z-index: 1000;
}
}
video {
width: 300px;
}
dl {
display: grid;
grid-template-columns: min-content auto;
gap: 0.5em 1em;
}
dt {
grid-column-start: 1;
margin: 0 !important;
}
dd {
grid-column-start: 2;
margin: 0 0 1em 0 !important;
}
@media (prefers-reduced-motion: reduce) {
#webgl-confetti {
display: none !important;
}
}
================================================
FILE: assets/css/articles/callable.scss
================================================
dl {
display: grid;
grid-template-columns: min-content auto;
gap: 0.5em 1em;
}
dt {
grid-column-start: 1;
margin: 0 !important;
}
dd {
grid-column-start: 2;
margin: 0 0 1em 0 !important;
}
================================================
FILE: assets/css/articles/characterset.scss
================================================
@import "colors";
@import "functions";
.conversation {
@include clearfix;
margin: 1em auto;
max-width: 650px;
ruby {
ruby-align: start;
ruby-position: over;
display: block;
clear: both;
max-width: 550px;
&.boke {
float: left;
text-align: left;
margin-bottom: 0.5em;
}
&.tsukkomi {
float: right;
color: var(--orange);
text-align: right;
margin-bottom: 1.5em;
}
}
}
================================================
FILE: assets/css/articles/dark-mode.scss
================================================
.color {
background: var(--color);
display: inline-block;
}
p .color {
width: 0.8em;
height: 0.8em;
border-radius: 0.2ch;
}
table {
table-layout: auto;
thead {
tr:not(:first-of-type) th {
font-weight: normal;
font-size: 0.5em;
}
}
td {
padding: 0.5em 0 !important;
}
.color {
width: 64px;
height: 64px;
border-radius: 8px;
display: block;
margin: 0 auto;
}
}
td.dark {
background: #2c2a28;
}
@media (prefers-color-scheme: dark) {
td.light {
background: #fefefe;
}
}
@media screen and (max-width: 768px) {
table td .color {
width: 32px;
height: 32px;
border-radius: 4px;
}
}
#fixed-colors {
display: grid;
grid-template-columns: 1fr 0 1fr;
}
@media screen and (min-width: 768px) {
#semantic-colors {
column-count: 2;
column-fill: balance;
dl {
margin-top: 0;
padding-top: 0;
}
dt {
margin-top: 2em;
}
dd {
break-before: avoid;
break-inside: avoid;
-webkit-column-break-before: avoid;
margin-bottom: 0.5em;
&:before {
content: "• ";
}
}
}
}
================================================
FILE: assets/css/articles/formatter.scss
================================================
dl {
width: auto;
font-family: initial;
display: grid;
grid-template-columns: auto max-content;
gap: 0 1em;
padding: 1em 0;
border-top: 1px solid;
border-bottom: 1px solid;
margin: 2em 0;
}
dt {
grid-column-start: 1;
margin: 0 !important;
}
dd {
grid-column-start: 2;
margin: 0 0 1em 0 !important;
&:before {
content: "• "
}
}
dd + dt {
&, & + dd {
padding-top: 2em;
}
}
================================================
FILE: assets/css/articles/ios-13.scss
================================================
.conversation {
max-width: 50ch;
display: block;
margin: 0 auto;
padding: 1em 0;
p {
margin: 0;
}
p:nth-of-type(2n) {
display: block;
font-style: italic;
text-align: right;
padding: 0.5em 0 1em 1em;
&::first-letter {
font-style: normal;
}
}
}
#on-device-speech-recognition-supported-languages {
text-align: left;
dl{
display: grid;
gap: 1em 2em;
grid-template-columns: repeat(1fr);
}
dt {
grid-column-start: 1;
margin: 0;
padding: 0;
text-align: right;
}
dd {
grid-column-start: 2;
margin: 0;
padding: 0;
}
}
================================================
FILE: assets/css/articles/keyvaluepairs.scss
================================================
#bagua {
td {
text-align: center;
}
}
#bagua + p ruby:last-of-type {
-webkit-ruby-position: under;
ruby-position: under;
}
rtc {
display: none !important;
}
================================================
FILE: assets/css/articles/mapkit-js.scss
================================================
#jwt-debug {
h3 {
margin: 0;
small {
display: block;
font-weight: normal;
font-size: smaller;
}
}
display: grid;
grid-template:
"encoded header"
"encoded payload"
"encoded signature";
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 0.5em 3em;
#jwt-encoded {
grid-area: encoded;
.highlight {
font-size: larger;
height: 86%;
}
}
#jwt-header {
grid-area: header;
span.s2 {
color: var(--pink) !important;
}
}
#jwt-payload {
grid-area: payload;
span.s2 {
color: var(--purple) !important;
}
}
#jwt-signature {
grid-area: signature;
span.s2,
span.nx {
color: var(--teal) !important;
}
}
#jwt-header,
#jwt-payload,
#jwt-signature {
.highlight {
font-size: smaller;
}
}
}
#map {
display: block;
width: 100%;
height: 400px;
margin-bottom: 2em;
}
.mk-map-view {
border: 1px transparent solid;
border-radius: 4px;
}
@media screen and (max-width: 768px) {
#jwt-debug {
grid-template:
"encoded"
"header"
"payload"
"signature";
grid-template-columns: auto;
grid-template-rows: auto;
gap: 0.5em 0;
}
}
================================================
FILE: assets/css/articles/message-id.scss
================================================
@import "../functions";
@media screen and (min-width: 768px) {
aside {
@include clearfix;
figure {
float: right;
padding-left: 20px;
margin: 0 !important;
padding: 0 !important;
img {
margin: 0 !important;
}
& + p:first-of-type {
margin-top: 2em;
}
}
}
}
================================================
FILE: assets/css/articles/metrickit.scss
================================================
h2 {
clear: both;
}
@media screen and (min-width: 768px) {
#battery-usage {
float: right;
width: 300px;
padding-left: 20px;
}
}
================================================
FILE: assets/css/articles/model-context-protocol.scss
================================================
ol {
list-style-type: decimal !important;
}
@media (min-width: 768px) {
dl {
margin-left: auto;
margin-right: auto;
width: 85%;
}
dt,
dd {
padding-left: 2rem;
padding-right: 2rem;
}
}
dl {
border: 1px solid #b7b7b7;
padding: 1rem;
margin-top: 0.25rem;
margin-bottom: 3rem;
font-size: 0.8rem;
dt,
dd {
padding-left: 1rem;
padding-right: 1rem;
}
dd {
margin-left: 0;
}
dt {
padding-top: 1rem;
margin-bottom: 0.125rem;
&:first-of-type {
padding-top: 0;
}
}
}
.user {
text-align: left;
}
.client {
text-align: center;
}
.assistant {
text-align: right;
blockquote {
text-align: right !important;
border-left: 0;
}
}
[role="article"] .content dl blockquote {
text-align: right !important;
border-left: 0 !important;
margin: 0;
font-style: italic;
}
span.big {
font-size: 2rem;
padding-top: 0.5rem;
display: inline-block;
}
picture img[src$=".svg"] {
filter: none !important;
}
#imcp-logo {
max-width: 480px;
display: block;
margin: 0 auto;
cursor: pointer;
}
#emcee-logo {
max-width: 480px;
display: block;
margin: 0 auto;
cursor: pointer;
}
================================================
FILE: assets/css/articles/swift-format.scss
================================================
div.variable-width {
resize: horizontal;
overflow: hidden;
min-width: 30ch;
width: 30ch;
max-width: 100%;
margin-bottom: 2em;
.highlight {
height: 80vh;
overflow: scroll;
font-size: 14px !important;
line-height: 1.2 !important;
}
}
================================================
FILE: assets/css/articles/swift-log.scss
================================================
#log-levels {
table-layout: auto;
tbody td:first-of-type {
background-color: var(--color);
code {
background-color: var(--background);
color: var(--text) !important;
display: block;
}
}
}
#log-level-trace {
--color: var(--gray);
}
#log-level-debug {
--color: var(--blue);
}
#log-level-info {
--color: var(--green);
}
#log-level-notice {
--color: var(--yellow);
}
#log-level-warning {
--color: var(--orange);
}
#log-level-error {
--color: var(--red);
}
#log-level-critical {
--color: black;
}
================================================
FILE: assets/css/articles/swift-package-registry.scss
================================================
table {
table-layout: auto !important;
td {
text-align: right !important;
}
}
.dialogue {
text-align: left !important;
margin: 1em auto;
code,
samp {
display: inline-block;
line-height: 1.6;
}
var.placeholder {
padding: 0 0.25em;
}
code {
color: var(--code);
i {
color: var(--gray);
font-style: normal;
}
}
details {
margin: 0.5em 0;
padding: 0.5em 0;
padding-left: 2em;
border-top: 1px dotted var(--separator);
border-bottom: 1px dotted var(--separator);
summary {
margin-left: -2em;
margin-bottom: 0;
}
}
pre {
width: auto;
display: block;
clear: both;
margin: 0;
}
samp {
overflow: none;
line-height: 1.2;
color: var(--gray);
margin-bottom: 0.5em;
padding: 0.25em 0;
font-style: italic;
}
.placeholder {
color: var(--gray) !important;
}
}
@media screen and (min-width: 768px) {
.dialogue,
details {
&::after {
content: "";
clear: both;
display: table;
}
}
.dialogue {
padding: 0.5em 2em !important;
.input {
text-align: left;
}
.output {
float: right;
}
}
}
================================================
FILE: assets/css/articles/swiftui-previews.scss
================================================
.code-with-automatic-preview {
display: flex;
align-items: stretch;
background-color: var(--secondary-background);
margin-bottom: 2em;
.highlight {
flex: 2;
}
aside {
flex: 1;
max-width: 400px;
border-left: 1px var(--opaque-separator) solid;
background-color: var(--secondary-background);
margin-left: 20px;
padding: 10px;
}
}
================================================
FILE: assets/css/fonts/_batang.scss
================================================
@font-face {
font-family: 'Batang';
src: url(font_path("Batang.woff2")) format("woff2"),
url(font_path("Batang.woff")) format("woff");
font-weight: normal;
font-style: normal;
font-display: auto;
unicode-range: U+AC00-D7A3, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
}
================================================
FILE: assets/css/fonts/_cc.scss
================================================
@font-face {
font-family: "Creative Commons Symbols";
src: url(font_path("CreativeCommonsSymbols.woff2")) format("woff2"),
url(font_path("CreativeCommonsSymbols.woff")) format("woff");
font-weight: normal;
font-style: normal;
unicode-range: U+1F10D-1F10F, U+1F16D-1F16F;
}
================================================
FILE: assets/css/fonts/_merriweather.scss
================================================
@font-face {
font-family: "Merriweather";
src: local("Merriweather Regular"), local("Merriweather-Regular"),
url(font_path("Merriweather-Regular.woff2")) format("woff2"),
url(font_path("Merriweather-Regular.woff")) format("woff");
font-weight: normal;
font-style: normal;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Light"), local("Merriweather-Light"),
url(font_path("Merriweather-Light.woff2")) format("woff2"),
url(font_path("Merriweather-Light.woff")) format("woff");
font-weight: 300;
font-style: normal;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Black"), local("Merriweather-Black"),
url(font_path("Merriweather-Black.woff2")) format("woff2"),
url(font_path("Merriweather-Black.woff")) format("woff");
font-weight: 900;
font-style: normal;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Bold"), local("Merriweather-Bold"),
url(font_path("Merriweather-Bold.woff2")) format("woff2"),
url(font_path("Merriweather-Bold.woff")) format("woff");
font-weight: bold;
font-style: normal;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Black Italic"), local("Merriweather-BlackItalic"),
url(font_path("Merriweather-BlackItalic.woff2")) format("woff2"),
url(font_path("Merriweather-BlackItalic.woff")) format("woff");
font-weight: 900;
font-style: italic;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Italic"), local("Merriweather-Italic"),
url(font_path("Merriweather-Italic.woff2")) format("woff2"),
url(font_path("Merriweather-Italic.woff")) format("woff");
font-weight: normal;
font-style: italic;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Bold Italic"), local("Merriweather-BoldItalic"),
url(font_path("Merriweather-BoldItalic.woff2")) format("woff2"),
url(font_path("Merriweather-BoldItalic.woff")) format("woff");
font-weight: bold;
font-style: italic;
font-display: auto;
}
@font-face {
font-family: "Merriweather";
src: local("Merriweather Light Italic"), local("Merriweather-LightItalic"),
url(font_path("Merriweather-LightItalic.woff2")) format("woff2"),
url(font_path("Merriweather-LightItalic.woff")) format("woff");
font-weight: 300;
font-style: italic;
font-display: auto;
}
================================================
FILE: assets/css/media-queries/_hover.scss
================================================
@media (hover: none) {
#logo #mustache {
animation-iteration-count: 1;
}
}
================================================
FILE: assets/css/media-queries/_inverted-colors.scss
================================================
@media (inverted-colors) {
* {
text-shadow: none !important;
box-shadow: none !important;
}
img {
filter: invert(100%);
}
}
================================================
FILE: assets/css/media-queries/_monochrome.scss
================================================
@media (monochrome),
print and (not(color)),
(prefers-contrast: high),
screen and (-ms-high-contrast: active) {
:root {
--red: black;
--yellow: black;
--green: black;
--teal: black;
--blue: black;
--indigo: black;
--purple: black;
--pink: black;
--gray: black;
--gray2: black;
--gray3: black;
--gray4: black;
--gray5: black;
--gray6: black;
--text: black;
--secondary-text: black;
--placeholder-text: black;
--separator: black;
--opaque-separator: black;
--fill: white;
--secondary-fill: white;
--background: white;
--secondary-background: white;
}
.highlight {
color: black !important;
background: #fff !important;
border: 2px black solid;
.c,
.ch,
.cm,
.cpf,
.c1,
.cs,
.ge,
.s,
.sa,
.sb,
.sc,
.dl,
.sd,
.s2,
.sh,
.sx,
.sr,
.s1,
.ss {
font-style: italic;
}
.k,
.gh,
.gp,
.gs,
.gu,
.kc,
.kd,
.kn,
.kr,
.nc,
.ni,
.ne,
.nn,
.nt,
.ow {
font-weight: bold;
}
.se,
.si {
font-weight: bold;
font-style: italic;
}
}
.admonition:before {
visibility: hidden;
}
}
================================================
FILE: assets/css/media-queries/_prefers-color-scheme.scss
================================================
@media (prefers-color-scheme: dark) {
:root {
--red: rgb(255, 69, 58);
--yellow: rgb(255, 214, 10);
--green: rgb(48, 209, 88);
--teal: rgb(100, 210, 255);
--blue: rgb(10, 132, 255);
--indigo: rgb(94, 92, 230);
--purple: rgb(191, 90, 242);
--pink: rgb(255, 55, 95);
--gray: rgb(142, 142, 147);
--gray2: rgb(99, 99, 102);
--gray3: rgb(72, 72, 74);
--gray4: rgb(58, 58, 60);
--gray5: rgb(44, 44, 46);
--gray6: rgb(28, 28, 30);
--text: rgb(255, 255, 255);
--secondary-text: rgb(235, 235, 245);
--placeholder-text: rgb(235, 235, 245);
--separator: rgb(84, 84, 88);
--opaque-separator: rgb(56, 56, 58);
--fill: rgb(120, 120, 128);
--secondary-fill: rgb(120, 120, 128);
--background: rgb(14, 14, 15);
--secondary-background: rgb(28, 28, 30);
}
@supports (color: color(display-p3 1 1 1)) {
:root {
--red: color(display-p3 1 0.4118 0.3804);
--yellow: color(display-p3 1 0.8314 0.149);
--green: color(display-p3 0.1882 0.8588 0.3569);
--teal: color(display-p3 0.4392 0.8431 1);
--blue: color(display-p3 0.251 0.6118 1);
--indigo: color(display-p3 0.4902 0.4784 1);
--purple: color(display-p3 0.8549 0.5608 1);
--pink: color(display-p3 1 0.3922 0.5098);
--gray: color(display-p3 0.6824 0.6824 0.698);
--gray2: color(display-p3 0.4863 0.4863 0.502);
--gray3: color(display-p3 0.3294 0.3294 0.3373);
--gray4: color(display-p3 0.2667 0.2667 0.2745);
--gray5: color(display-p3 0.2118 0.2118 0.2196);
--gray6: color(display-p3 0.1412 0.1412 0.149);
--text: color(display-p3 1 1 1);
--secondary-text: color(display-p3 0.9216 0.9216 0.9608);
--placeholder-text: color(display-p3 0.9216 0.9216 0.9608);
--separator: color(display-p3 0.3294 0.3294 0.3451);
--opaque-separator: color(display-p3 0.2196 0.2196 0.2275);
--fill: color(display-p3 0.4706 0.4706 0.502);
--secondary-fill: color(display-p3 0.4706 0.4706 0.502);
--background: color(display-p3 0.0706 0.0706 0.075);
--secondary-background: color(display-p3 0.1412 0.1412 0.149);
}
}
body {
div.highlight {
border: 1px var(--separator) solid !important;
}
.language-toggle a {
color: var(--secondary-text) !important;
}
.info {
background: #333c44 !important;
}
.warning {
background: #484131 !important;
}
.error {
background: #592e41 !important;
}
}
article,
i {
img[src$=".svg"] {
filter: invert(100%);
}
}
kbd {
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 0 2px #222 inset;
}
}
================================================
FILE: assets/css/media-queries/_prefers-contrast.scss
================================================
@media (prefers-contrast: high), screen and (-ms-high-contrast: active) {
:root {
--red: rgb(215, 0, 21);
--yellow: rgb(179, 98, 0);
--green: rgb(36, 138, 61);
--teal: rgb(0, 113, 164);
--blue: rgb(0, 64, 221);
--indigo: rgb(54, 52, 163);
--purple: rgb(137, 68, 171);
--pink: rgb(211, 15, 69);
--gray: rgb(108, 108, 112);
--gray2: rgb(142, 142, 147);
--gray3: rgb(174, 174, 178);
--gray4: rgb(188, 188, 192);
--gray5: rgb(216, 216, 220);
--gray6: rgb(235, 235, 240);
--text: rgb(0, 0, 0);
--secondary-text: rgb(60, 60, 67);
--placeholder-text: rgb(60, 60, 67);
--separator: rgb(60, 60, 67);
--opaque-separator: rgb(198, 198, 200);
--fill: rgb(120, 120, 128);
--secondary-fill: rgb(120, 120, 128);
--background: rgb(235, 235, 240);
--secondary-background: rgb(255, 255, 255);
}
@supports (color: color(display-p3 1 1 1)) {
:root {
--red: color(display-p3 0.8431 0 0.08235);
--yellow: color(display-p3 0.702 0.3843 0);
--green: color(display-p3 0.1412 0.5412 0.2392);
--teal: color(display-p3 0 0.4431 0.6431);
--blue: color(display-p3 0 0.251 0.8667);
--indigo: color(display-p3 0.2118 0.2039 0.6392);
--purple: color(display-p3 0.5373 0.2667 0.6706);
--pink: color(display-p3 0.8275 0.05882 0.2706);
--gray: color(display-p3 0.4235 0.4235 0.4392);
--gray2: color(display-p3 0.5569 0.5569 0.5765);
--gray3: color(display-p3 0.6824 0.6824 0.698);
--gray4: color(display-p3 0.7373 0.7373 0.7529);
--gray5: color(display-p3 0.8471 0.8471 0.8627);
--gray6: color(display-p3 0.9216 0.9216 0.9412);
--text: color(display-p3 0 0 0);
--secondary-text: color(display-p3 0.2353 0.2353 0.2627);
--placeholder-text: color(display-p3 0.2353 0.2353 0.2627);
--separator: color(display-p3 0.2353 0.2353 0.2627);
--opaque-separator: color(display-p3 0.7765 0.7765 0.7843);
--fill: color(display-p3 0.4706 0.4706 0.502);
--secondary-fill: color(display-p3 0.4706 0.4706 0.502);
--background: color(display-p3 0.9216 0.9216 0.9412);
--secondary-background: color(display-p3 1 1 1);
}
}
}
================================================
FILE: assets/css/media-queries/_prefers-reduced-motion.scss
================================================
@media (prefers-reduced-motion: reduce) {
#logo #mustache {
animation: none !important;
}
}
================================================
FILE: assets/css/media-queries/_print.scss
================================================
@media print {
@page {
margin: 0.5in;
}
@page {
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: small;
}
@footnote {
border-top: 1pt black solid;
padding-top: 1em;
font-size: smaller;
padding-left: 1.5em;
}
}
html {
border-top: none;
body {
font-size: 12pt !important;
}
}
#logo {
height: 3em !important;
svg {
transform: scale(0.5);
transform-origin: top left;
}
}
img,
p,
blockquote,
aside,
ul,
ol,
table,
figure,
.highlight-group {
page-break-inside: avoid;
}
.highlight-group {
page-break-before: avoid;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-before: avoid;
page-break-after: avoid;
}
img {
max-width: 100% !important;
}
p {
a {
word-wrap: break-word;
}
a[href^="#"]:after {
display: none;
}
a[href^="http://"]:after,
a[href^="https://"]:after {
// content: " ("attr(href) ")";
// text-decoration: underline;
content: " (" attr(title) ") ";
float: footnote;
color: var(--secondary-text);
font-size: small;
text-decoration: none;
text-align: left;
page-break-inside: avoid;
page-break-before: avoid;
}
}
article [title]::after {
content: " (" attr(title) ") ";
float: footnote;
font-size: small;
}
.highlight-group a {
font-size: 50%;
}
div.highlight {
border-radius: 4px;
border: 2px black solid;
}
[role="article"] {
.content {
margin-bottom: 1em !important;
}
}
[role="complementary"] {
display: none;
}
[role="contentinfo"] {
page-break-inside: avoid;
font-size: small;
}
.admonition {
padding: 0 0 0 1em;
&::before {
visibility: hidden;
}
}
[hidden] {
display: none !important;
}
}
@media print and (color) {
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
================================================
FILE: assets/css/media-queries/_width.scss
================================================
@media screen and (max-width: 768px) {
[role="article"] header {
.byline {
.authors,
.translators {
&:after {
content: " ";
display: block;
}
}
}
}
.container {
padding: 1em;
}
#recent {
ul {
display: block;
li {
min-height: auto;
margin-bottom: 2em;
.title {
display: block;
height: auto;
padding-bottom: 0.5rem;
}
}
}
}
[role="article"] {
font-size: smaller;
.content {
overflow: hidden;
blockquote {
margin: 1em 0;
}
}
footer .contributor {
width: 100%;
margin-bottom: 1em;
&:not(:first-child) {
border-top: none;
}
.avatar {
padding: 0;
}
.details {
margin-top: 0;
}
}
}
[role="complementary"] {
#continue,
#related {
width: 100%;
}
#related {
margin-top: 1em;
li {
font-size: 1em;
}
}
}
#contributors ul li {
flex-basis: 33%;
}
#recent article {
float: none;
display: block;
width: 100%;
&:last-child,
&:nth-of-type(2n) {
margin-right: 0;
}
}
.archive dl {
width: 100%;
margin: 0;
float: none;
dt {
margin: 2em 0 0.5em 0;
}
}
#archive dd {
min-height: 30px;
}
}
@media screen and (max-width: 960px) {
[role="banner"] {
display: block;
margin-bottom: 0;
padding-bottom: 0;
#logo {
margin: 0 !important;
height: auto;
svg {
width: 25vw;
display: block;
margin: 0 auto 1.5em auto;
}
padding-bottom: 0.5em;
}
.tagline {
font-size: 4.4vw;
padding-bottom: 2em;
}
}
#recent {
ul {
grid-template-columns: repeat(2, 1fr);
}
}
.anchor {
font-size: smaller;
}
#announcement {
margin-left: 0;
margin-right: 0;
}
article.author,
article.translator {
header {
display: block;
.avatar {
margin: 0 auto 1em auto;
display: block;
}
h1 {
text-align: center;
}
}
}
}
@media screen and (max-width: 768px) {
#promotion {
padding-top: 3em;
small {
position: relative;
top: 60px;
}
article {
padding-top: 80px;
}
.book {
img {
width: 350px;
margin: -86px auto 0 280px;
position: absolute;
}
}
.buy {
width: 100%;
}
}
}
@media screen and (max-width: 480px) {
#promotion {
padding-top: 0;
small {
text-align: center;
display: block;
}
article {
overflow: hidden;
}
h3 {
padding-right: 3em;
}
.book {
margin: -30px 0 0 0;
img {
width: 320px;
margin: 0;
padding: 0;
position: relative;
left: -10px;
}
& + div {
clear: both;
}
}
}
}
================================================
FILE: assets/css/screen.scss
================================================
@charset "UTF-8";
@import "colors";
@import "animations";
@import "typography";
@import "admonitions";
@import "layout";
@import "code";
@import "inputs";
@import "media-queries/width";
@import "media-queries/hover";
@import "media-queries/inverted-colors";
@import "media-queries/monochrome";
@import "media-queries/prefers-color-scheme";
@import "media-queries/prefers-contrast";
@import "media-queries/prefers-reduced-motion";
@import "media-queries/print";
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#type-encodings tr > td:first-child,
#method-encodings tr > td:first-child {
width: 12em;
padding-left: 3em;
}
@media screen and (max-width: 480px) {
#gpuimage table {
font-size: 50%;
}
}
#gpuimage {
#gpuimage-benchmarks td {
text-align: center;
&:first-child {
text-align: left;
}
&:last-child {
text-align: right;
}
}
#gpuimage-filters td {
vertical-align: top;
font-size: 75%;
}
blockquote {
font-size: 75%;
}
}
table {
&.core-data-versus-nskeyedarchiver td {
text-align: center;
&:first-child {
text-align: left;
font-weight: bold;
}
}
ode-key-bindings-modifiers {
width: 100%;
td,
th {
width: 20%;
text-align: center;
}
}
}
#cfstringtransform table {
display: block;
td:first-child {
width: 60%;
}
}
#icloud header time {
background-color: rgba(255, 128, 0, 0.2);
}
================================================
FILE: assets/js/application.js
================================================
"use strict";
(function() {
const delay = 300;
const keys = {
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40
};
const direction = {
37: -1,
39: 1
};
const tablists = document.querySelectorAll('[role="tablist"]');
tablists.forEach(tablist => {
const tabs = tablist.querySelectorAll('[role="tab"]');
const panels = tablist.parentElement.querySelectorAll('[role="tabpanel"]');
const clickEventListener = event => {
const target = event.target;
target.dispatchEvent(
new Event("activate", {
bubbles: true
})
);
};
const keydownEventListener = event => {
const { keyCode } = event;
switch (keyCode) {
case keys.end:
event.preventDefault();
tabs[tabs.length - 1].dispatchEvent(
new Event("activate", {
bubbles: true
})
);
break;
case keys.home:
event.preventDefault();
tabs[0].dispatchEvent(
new Event("activate", {
bubbles: true
})
);
break;
case keys.up:
case keys.down:
determineOrientation(event);
break;
}
};
const keyupEventListener = event => {
const { keyCode, target } = event;
tabs.forEach(tab => {
tab.addEventListener("focus", focusEventListener);
});
if (direction[keyCode]) {
if (target.dataset.index !== undefined) {
if (tabs[target.dataset.index + direction[pressed]]) {
tabs[target.dataset.index + direction[pressed]].focus();
} else if (pressed === keys.left || pressed === keys.up) {
tabs[tabs.length - 1].focus();
} else if (pressed === keys.right || pressed == keys.down) {
tabs[0].focus();
}
}
}
};
const focusEventListener = event => {
const { target } = event;
const handler = target => {
focused = document.activeElement;
if (target === focused) {
target.dispatchEvent(new Event("activate"));
}
};
setTimeout(handler, delay, target);
};
const activateEventListener = event => {
const { target, bubbles } = event;
tabs.forEach(tab => {
tab.setAttribute("tabindex", "-1");
tab.setAttribute("aria-selected", "false");
tab.removeEventListener("focus", focusEventListener);
});
panels.forEach(panel => {
panel.setAttribute("hidden", "hidden");
});
target.removeAttribute("tabindex");
target.setAttribute("aria-selected", "true");
var controls = target.getAttribute("aria-controls");
document.getElementById(controls).removeAttribute("hidden");
if (bubbles) {
for (const language of ["swift", "objective-c"]) {
if (target.classList.contains(language)) {
if (window.localStorage) {
window.localStorage.setItem("preferred-language", language);
}
document
.querySelectorAll(`[role="tab"].${language}`)
.forEach(tab => {
tab.dispatchEvent(new Event("activate"));
});
document.querySelectorAll(".highlight-group").forEach(group => {
if (
group.clientHeight > (parseInt(group.style.minHeight, 10) || 0)
) {
group.style.minHeight = `${group.clientHeight}px`;
}
});
}
}
}
};
for (let index = 0; index < tabs.length; index++) {
const tab = tabs[index];
tab.addEventListener("click", clickEventListener);
tab.addEventListener("keydown", keydownEventListener);
tab.addEventListener("keyup", keyupEventListener);
tab.addEventListener("activate", activateEventListener);
tab.dataset.index = index;
}
});
if (window.localStorage) {
const language = window.localStorage.getItem("preferred-language");
if (language) {
document.querySelectorAll(`[role="tab"].${language}`).forEach(tab => {
tab.dispatchEvent(new Event("activate"));
});
}
}
document
.querySelectorAll('article [role="heading"] h1.title')
.forEach(element => {
const resize = () => {
const compression = 1.0;
const minFontSize = 16.0;
const maxFontSize = 72.0;
element.style.fontSize =
Math.max(
Math.min(element.clientWidth / (compression * 10), maxFontSize),
minFontSize
) + "px";
};
resize();
window.addEventListener("resize", resize);
window.addEventListener("orientationchange", resize);
});
})();
setTimeout(function() {
if (
document.location.pathname === "/" &&
matchMedia("(hover: none)").matches
) {
document.querySelector("#logo svg").classList.add("animated");
}
}, 1000);
================================================
FILE: assets/js/articles/caemitterlayer.js
================================================
// Credit: https://jsfiddle.net/subzey/52sowezj/
'use strict';
(function() {
var canvas = document.querySelector('#webgl-confetti canvas');
var gl = canvas.getContext('webgl', {alpha: true});
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, `
precision lowp float;
attribute vec2 a_position;
attribute float a_startAngle;
attribute float a_angularVelocity;
attribute float a_rotationAxisAngle;
attribute float a_particleDistance;
attribute float a_particleAngle;
attribute float a_particleY;
uniform float u_time;
varying vec2 v_position;
varying vec3 v_color;
varying float v_overlight;
void main() {
float angle = a_startAngle + a_angularVelocity * u_time;
float vertPosition = 1.1 - mod(u_time * .25 + a_particleY, 2.2);
float viewAngle = a_particleAngle + mod(u_time * .25, 6.28);
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,
1.0, 0.0, 0.0, 0.0, 1.0);
mat4 shiftMatrix =
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,
a_particleDistance * sin(viewAngle), vertPosition,
a_particleDistance * cos(viewAngle), 1.0);
mat4 pMatrix = mat4(cos(a_rotationAxisAngle), sin(a_rotationAxisAngle), 0.0,
0.0, -sin(a_rotationAxisAngle), cos(a_rotationAxisAngle),
0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) *
mat4(1.0, 0.0, 0.0, 0.0, 0.0, cos(angle), sin(angle), 0.0, 0.0,
-sin(angle), cos(angle), 0.0, 0.0, 0.0, 0.0, 1.0);
gl_Position =
vMatrix * shiftMatrix * pMatrix * vec4(a_position * 0.03, 0.0, 1.0);
vec4 normal = vec4(0.0, 0.0, 1.0, 0.0);
vec4 transformedNormal = normalize(pMatrix * normal);
float dotNormal = abs(dot(normal.xyz, transformedNormal.xyz));
float regularLighting = dotNormal / 2.0 + 0.5;
float glanceLighting = smoothstep(0.92, 0.98, dotNormal);
v_color = vec3(mix((0.5 - transformedNormal.z / 2.0) * regularLighting, 1.0,
glanceLighting),
mix(0.5 * regularLighting, 1.0, glanceLighting),
mix((0.5 + transformedNormal.z / 2.0) * regularLighting, 1.0,
glanceLighting));
v_position = a_position;
v_overlight = 0.9 + glanceLighting * 0.1;
}
`);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, `
precision lowp float;
varying vec2 v_position;
varying vec3 v_color;
varying float v_overlight;
void main() {
gl_FragColor =
vec4(v_color, 1.0 - smoothstep(0.8, v_overlight, length(v_position)));
}
`);
gl.compileShader(fragmentShader);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
var STRIDE = 8;
var attrs = [
{name: 'a_position', length: 2, offset: 0},
{name: 'a_startAngle', length: 1, offset: 2},
{name: 'a_angularVelocity', length: 1, offset: 3},
{name: 'a_rotationAxisAngle', length: 1, offset: 4},
{name: 'a_particleDistance', length: 1, offset: 5},
{name: 'a_particleAngle', length: 1, offset: 6},
{name: 'a_particleY', length: 1, offset: 7}
];
for (var i = 0; i < attrs.length; i++) {
var name = attrs[i].name;
var length = attrs[i].length;
var offset = attrs[i].offset;
var attribLocation = gl.getAttribLocation(shaderProgram, name);
gl.vertexAttribPointer(
attribLocation, length, gl.FLOAT, false, STRIDE * 4, offset * 4);
gl.enableVertexAttribArray(attribLocation);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
var NUM_PARTICLES = 150;
var NUM_VERTICES = 4;
var NUM_INDICES = 6;
var vertices = new Float32Array(NUM_PARTICLES * STRIDE * NUM_VERTICES);
var indices = new Uint16Array(NUM_PARTICLES * NUM_INDICES);
for (var i = 0; i < NUM_PARTICLES; i++) {
var axisAngle = Math.random() * Math.PI * 2;
var startAngle = Math.random() * Math.PI * 2;
var groupPtr = i * STRIDE * NUM_VERTICES;
var particleDistance = Math.sqrt(Math.random());
var particleAngle = Math.random() * Math.PI * 2;
var particleY = Math.random() * 2.2;
var angularVelocity = Math.random() * 2 + 1;
for (var j = 0; j < 4; j++) {
var vertexPtr = groupPtr + j * STRIDE;
vertices[vertexPtr + 2] = startAngle;
vertices[vertexPtr + 3] = angularVelocity;
vertices[vertexPtr + 4] = axisAngle;
vertices[vertexPtr + 5] = particleDistance;
vertices[vertexPtr + 6] = particleAngle;
vertices[vertexPtr + 7] = particleY;
}
vertices[groupPtr] = vertices[groupPtr + STRIDE * 2] = -1;
vertices[groupPtr + STRIDE] = vertices[groupPtr + STRIDE * 3] = 1;
vertices[groupPtr + 1] = vertices[groupPtr + STRIDE + 1] = -1;
vertices[groupPtr + STRIDE * 2 + 1] = vertices[groupPtr + STRIDE * 3 + 1] = 1;
var indicesPtr = i * NUM_INDICES;
var vertexPtr = i * NUM_VERTICES;
indices[indicesPtr] = vertexPtr;
indices[indicesPtr + 4] = indices[indicesPtr + 1] = vertexPtr + 1;
indices[indicesPtr + 3] = indices[indicesPtr + 2] = vertexPtr + 2;
indices[indicesPtr + 5] = vertexPtr + 3;
}
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
var timeUniformLocation = gl.getUniformLocation(shaderProgram, 'u_time');
var startTime = (window.performance || Date).now();
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.viewport(0, 0, canvas.width, canvas.height);
function frame() {
gl.uniform1f(
timeUniformLocation,
((window.performance || Date).now() - startTime) / 1000);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(
gl.TRIANGLES, NUM_INDICES * NUM_PARTICLES, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(frame);
}
frame();
})();
================================================
FILE: assets/js/articles/mapkit-js.js
================================================
"use strict";
(function() {
mapkit.init({
authorizationCallback: done => {
done(
"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IjRUOTJZWlNXR00ifQ.eyJleHAiOjI0MTYzMjE2MDAuMjc2NjE2MSwiaXNzIjoiOUpXVkFEUjNSUSIsIm9yaWdpbiI6Imh0dHBzOlwvXC9uc2hpcHN0ZXIuY29tIiwiaWF0IjoxNTUyMzIxNjAwLjI3NjYxNzF9.DRsKD-6Y9MMVId46PnV9DK-YiobqGu0qCMbK1fYjglWOVnuJkpm4UGDdYLB0T4xJfStPlrSI1Pwbzsjn_i0Qww"
);
}
});
const center = new mapkit.Coordinate(37.3327, -122.0053),
span = new mapkit.CoordinateSpan(0.0125, 0.0125),
region = new mapkit.CoordinateRegion(center, span);
let map = new mapkit.Map("map", {
region: region,
showsCompass: mapkit.FeatureVisibility.Hidden,
showsZoomControl: false,
showsMapTypeControl: false
});
const annotation = new mapkit.MarkerAnnotation(center, {
title: "Apple Park Visitor Center",
subtitle: "10600 North Tantau Avenue, Cupertino, CA 95014",
glyphText: "",
color: "#8e8e93",
displayPriority: 1000
});
map.addAnnotation(annotation);
})();
================================================
FILE: assets/js/articles/swift-format.js
================================================
//= require vendor/resize-observer.min.js
"use strict";
function getComputedWidthInEm(element) {
const computed = window.getComputedStyle(element);
const regex = /(\d+(\.\d+)?)px$/;
const fontSize = Number(computed.fontSize.match(regex)[1]);
const width = Number(computed.width.match(regex)[1]);
return (width / fontSize) * 2.6;
}
(function() {
const container = document.querySelector(".variable-width");
const candidates = Array.from(document.querySelectorAll("[data-width]")).sort(
({ dataset: { width: a } }, { dataset: { width: b } }) => b.localeCompare(a)
);
const observer = new ResizeObserver(() => {
const targetWidth = getComputedWidthInEm(container);
var foundMatch = false;
candidates.forEach(element => {
const width = Number(element.dataset.width);
if (!width || foundMatch) {
element.setAttribute("hidden", "hidden");
} else if (width < targetWidth) {
foundMatch = true;
element.removeAttribute("hidden");
} else {
element.setAttribute("hidden", "hidden");
}
});
if (!foundMatch) {
candidates[candidates.length - 1].removeAttribute("hidden");
}
});
observer.observe(container);
})();
================================================
FILE: assets/js/articles/wwdc-2020.js
================================================
"use strict";
(function () {
const details = document.querySelector("details");
if (details) {
let listener = details.addEventListener("toggle", (event) => {
console.log("ADSFADSAFD");
const video = document.querySelector("video");
video.loop = true;
video.controls = false;
video.play();
details.removeEventListener("toggle", listener);
});
}
})();
================================================
FILE: assets/js/nsmutablehipster.js
================================================
//= require vendor/typed.min.js
"use strict";
(function() {
document.body.contentEditable = true;
document.querySelectorAll("a").forEach(element => {
element.contentEditable = false;
});
if (document.querySelector(".tagline")) {
new Typed(".tagline strong", {
strings: ["NSHipster", "NSMutableHipster"],
typeSpeed: 100,
backSpeed: 100,
startDelay: 1000,
onComplete: () => {
document.querySelector(".typed-cursor").remove();
}
});
document
.querySelector(".typed-cursor")
.setAttribute("style", "position: absolute;");
}
})();
================================================
FILE: assets/videos/TrickXORTreat.srt
================================================
1
00:00:02,500 --> 00:00:07,591
Every kid knows the phrase, [kid sing-songy] "Trick or treat!" But have you
2
00:00:07,691 --> 00:00:11,882
ever stopped to wonder — what kind of _"or"_ is that, exactly?
3
00:00:13,566 --> 00:00:20,150
Let's start with the obvious interpretation: Two circles—two children. Orange means
4
00:00:20,250 --> 00:00:25,063
treats, gray means tricks. This is inclusive OR: If any child
5
00:00:25,163 --> 00:00:29,976
knocks, everyone gets candy. Only an empty porch gets tricks.
6
00:00:30,076 --> 00:00:33,306
[quickly] [chuckles] Is this how Venn diagrams work? Not at all!
7
00:00:33,406 --> 00:00:36,323
But hey, it's Halloween—logic gets to wear a costume, too.
8
00:00:37,323 --> 00:00:40,651
[title] Trick AND Treat Both children must show up together, or
9
00:00:40,751 --> 00:00:44,459
nobody gets treats. [sarcastic] One lonely kid? Sorry, that's a trick.
10
00:00:45,459 --> 00:00:50,925
[title] Trick XOR Treat This house rewards exactly one visitor.
11
00:00:51,025 --> 00:00:55,077
Too few or too many, and everyone gets tricked.
12
00:00:57,377 --> 00:01:00,878
These three behaviors cover most houses on the block.
13
00:01:00,978 --> 00:01:04,140
But De Morgan's laws hint at something more... a
14
00:01:04,240 --> 00:01:08,353
theoretical complement to each. A spooky, inverted reflection.
15
00:01:08,953 --> 00:01:14,882
[spooky] What cursed operations lurk in the penumbra of reason?
16
00:01:14,982 --> 00:01:19,380
Let's face our fears and venture into the dark.
17
00:01:21,069 --> 00:01:24,576
[title] Trick NOR Treat: the Halloween hater. This neighbor
18
00:01:24,676 --> 00:01:27,938
only gives treats when nobody visits. [quick laugh] The
19
00:01:28,038 --> 00:01:29,955
only winning move is not to play.
20
00:01:30,955 --> 00:01:36,134
[title] Trick NAND Treat: NOT-AND—the reverse psychology neighbor. This
21
00:01:36,234 --> 00:01:40,521
house gives treats to everyone... except pairs. Come alone?
22
00:01:40,621 --> 00:01:44,833
Treats. Don't come at all? ...[chuckles] Also Treats. Come
23
00:01:44,933 --> 00:01:49,219
together? [mischievous] That's the only way to get tricked.
24
00:01:50,219 --> 00:01:55,675
[title] Trick XNOR Treat: the conformity enforcer—XOR inverted. This neighbor
25
00:01:55,775 --> 00:02:00,148
rewards matching behavior. Both kids visit, or both stay home?
26
00:02:00,248 --> 00:02:03,755
Treats. Just one kid? [judgmental] That's a trick.
27
00:02:06,555 --> 00:02:11,086
These bottom-row operations are... deeply strange. They're the
28
00:02:11,186 --> 00:02:15,268
kinds of houses you'd skip entirely. But mathematically?
29
00:02:15,368 --> 00:02:18,106
They're just as valid as the classics.
30
00:02:18,705 --> 00:02:20,877
So the next time a child asks [kid sing-songy]
31
00:02:20,977 --> 00:02:23,742
"trick or treat?", you now have the mathematically correct
32
00:02:23,842 --> 00:02:27,940
response: [annoying high-pitched nasal pedantic] "That depends—which logical operator
33
00:02:28,040 --> 00:02:31,249
are you implementing?" [quick laugh] ...though I wouldn't recommend
34
00:02:31,349 --> 00:02:33,521
it if you don't want your house getting egged.
================================================
FILE: collections/en/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: Croath Liu
email: Croath.Liu@gmail.com
url: https://twitter.com/cr0ath
twitter: cr0ath
github: croath
image: croath-liu.jpg
---
[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.
================================================
FILE: collections/en/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[Delisa Mason](https://delisa.me)
([@kattrali](https://twitter.com/kattrali))
is the creator of the Xcode Package Manager,
[Alcatraz](https://alcatraz.io),
as well as a [CocoaPods](https://cocoapods.org) Core Team member.
================================================
FILE: collections/en/_authors/em-lazer-walker.md
================================================
---
title: Em Lazer-Walker
name: Em Lazer-Walker
email: hi@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: em-lazer-walker.jpg
---
[Em Lazer-Walker](http://lazerwalker.com) ([@lazerwalker](https://twitter.com/lazerwalker))
makes experimental games, interactive art, and software tools.
================================================
FILE: collections/en/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/en/_authors/jemmons.md
================================================
---
title: "@jemmons"
name: jemmons
url: https://figure.ink
twitter: jemmons
github: jemmons
image: jemmons.jpg
---
Josh ([@jemmons](https://twitter.com/jemmons)) has led mobile development at
graphic.ly, Reverb, and now Retail Zipline.
He lives in Chicago and writes about Swift at [figure.ink](https://figure.ink).
================================================
FILE: collections/en/_authors/jordan-morgan.md
================================================
---
title: Jordan Morgan
name: Jordan Morgan
email: info@dreaminginbinary.co
url: https://dreaminginbinary.co
twitter: JordanMorgan10
github: JordanMorgan10
image: jordan-morgan.jpg
---
Jordan Morgan is a software developer from Ozark, who created
[Dreaming In Binary](https://dreaminginbinary.co)
as a creative outlet for his side projects.
Currently, he is an iOS engineer at [Buffer](https://buffer.com).
Jordan is focused on helping the community by
doing talks about iOS and remote work and
writing books and blogs posts,
and considers himself a lifelong student for all forms of software engineering.
================================================
FILE: collections/en/_authors/matt-massicotte.md
================================================
---
title: Matt Massicotte
name: Matt Massicotte
url: https://www.massicotte.org
github: mattmassicotte
image: matt-massicotte.jpg
---
[Matt](https://www.massicotte.org/about)
is a long-time developer for Apple platforms.
He's into programming, the outdoors, video games, music,
and progress towards a safe and fair world for all people.
================================================
FILE: collections/en/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
================================================
FILE: collections/en/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/en/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/en/_authors/reda-lemeden.md
================================================
---
title: Reda Lemeden
name: Reda Lemeden
email: hello@redalemeden.com
url: https://redalemeden.com
twitter: kaishin
github: kaishin
image: reda-lemeden.jpg
---
[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.
================================================
FILE: collections/en/_authors/zoe-smith.md
================================================
---
title: Zoë Smith
name: Zoë Smith
email: zoews@me.com
url: https://zoesmith.io/about
twitter: zoejessica
github: zoejessica
image: zoe-smith.jpg
---
[Zoë Smith](https://zoesmith.io/about)
[(@zoejessica)](https://twitter.com/zoejessica)
is a software developer for Apple platforms
and the creator of
[AccessControlKitty](https://github.com/zoejessica/accesscontrolkitty) and
[F\*\*\*ingIfCaseLetSyntax.com](http://fuckingifcaseletsyntax.com).
================================================
FILE: collections/en/_books/cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: http://schema.org/Discontinued
price: 29.00
number_of_pages: 296
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
date: 2014-06-03
---
================================================
FILE: collections/en/_books/fake-book-objective-c.md
================================================
---
name: "fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
availability: http://schema.org/Discontinued
book_url: https://gum.co/the-nshipster-fake-book
price: 19
number_of_pages: 115
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
date: 2014-06-03
---
================================================
FILE: collections/en/_books/flight-school-guide-to-swift-codable.md
================================================
---
name: flight-school-guide-to-swift-codable
title: Flight School Guide to Swift Codable
short_title: Flight School
sub_title: Guide to Swift Codable
author: Mattt
summary: >-
Make better apps with less code more quickly using Swift Codable.
image: flight-school-guide-to-swift-codable.svg
availability: http://schema.org/InStock
book_url: https://flightdotschool.com/books/codable
price: 29.00
number_of_pages: 140
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-1-949080-04-9
date: 2018-04-20
---
================================================
FILE: collections/en/_books/flight-school-guide-to-swift-numbers.md
================================================
---
name: flight-school-guide-to-swift-numbers
title: Flight School Guide to Swift Numbers
short_title: Flight School
sub_title: Guide to Swift Numbers
author: Mattt
summary: >-
Everything you need to know about working with numbers in Swift
image: flight-school-guide-to-swift-numbers.svg
availability: http://schema.org/InStock
book_url: https://flightdotschool.com/books/numbers
price: 29.00
number_of_pages: 120
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-1-949080-05-6
date: 2018-06-01
---
================================================
FILE: collections/en/_books/flight-school-guide-to-swift-strings.md
================================================
---
name: flight-school-guide-to-swift-strings
title: Flight School Guide to Swift Strings
short_title: Flight School
sub_title: Guide to Swift Strings
author: Mattt
summary: >-
A comprehensive reference for working with text in Swift and Foundation.
image: flight-school-guide-to-swift-strings.svg
availability: http://schema.org/InStock
book_url: https://flightdotschool.com/books/strings
price: 29.00
number_of_pages: 180
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-1-949080-08-7
date: 2019-02-01
---
================================================
FILE: collections/en/_books/nshipster.md
================================================
---
name: nshipster
title: "NSHipster: Obscure Topics in Objective-C, Swift, & Cocoa"
short_title: "NSHipster"
sub_title: "Obscure Topics in Objective-C, Swift, & Cocoa"
edition: 3rd Edition
author: Mattt
summary: >-
A hand-picked selection of articles and essays from NSHipster.com,
bound together in a single volume for convenient reference.
image: nshipster-obscure-topics-third-edition.png
availability: http://schema.org/InStock
book_url: https://gumroad.com/l/nshipster-third-edition-digital-only
price: 9.00
number_of_pages: 389
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-1-949080-26-1
date: 2019-12-17
---
================================================
FILE: collections/es/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: Croath Liu
email: Croath.Liu@gmail.com
url: https://twitter.com/cr0ath
twitter: cr0ath
github: croath
image: croath-liu.jpg
---
[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.
================================================
FILE: collections/es/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[Delisa Mason](https://delisa.me)
([@kattrali](https://twitter.com/kattrali))
is the creator of the Xcode Package Manager,
[Alcatraz](https://alcatraz.io),
as well as a [CocoaPods](https://cocoapods.org) Core Team member.
================================================
FILE: collections/es/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/es/_authors/jordan-morgan.md
================================================
---
title: Jordan Morgan
name: Jordan Morgan
email: info@dreaminginbinary.co
url: https://dreaminginbinary.co
twitter: JordanMorgan10
github: JordanMorgan10
image: jordan-morgan.jpg
---
Jordan Morgan is a software developer from Ozark, who created
[Dreaming In Binary](https://dreaminginbinary.co)
as a creative outlet for his side projects.
Currently, he is an iOS engineer at [Buffer](https://buffer.com).
Jordan is focused on helping the community by
doing talks about iOS and remote work and
writing books and blogs posts,
and considers himself a lifelong student for all forms of software engineering.
================================================
FILE: collections/es/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
google: 106751358503565042647
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
He is the founder of NSHipster and [Flight School](https://flightdotschool.com),
and the creator of several open source libraries,
including [AFNetworking](https://github.com/afnetworking/afnetworking)
and [Alamofire](https://github.com/alamofire/alamofire).
================================================
FILE: collections/es/_authors/mike-lazer-walker.md
================================================
---
title: Mike Lazer-Walker
name: Mike Lazer-Walker
email: michael@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: mike-lazer-walker.jpg
---
[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).
================================================
FILE: collections/es/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/es/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/es/_books/01-nshipster-swift.md
================================================
---
name: nshipster-swift
title: "NSHipster: Obscure Topics in Cocoa & Swift"
short_title: "NSHipster, Second Edition"
sub_title: "Obscure Topics in Cocoa & Swift"
author: Mattt & Nate Cook
summary: "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."
image: "nshipster-swift-cover@2x.png"
formats:
ebook:
isbn: 978-0-9912182-6-4
availability: in_stock
book_url: https://gum.co/nshipster-swift/
price: 29.00
number_of_pages: 288
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-6-4
date: 2015-04-18
---
================================================
FILE: collections/es/_books/02-cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: in_stock
book_url: https://gum.co/cfhipsterref
price: 29.00
number_of_pages: 296
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
date: 2014-06-03
---
================================================
FILE: collections/es/_books/03-nshipster-fake-book-objective-c.md
================================================
---
name: "nshipster-fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
availability: in_stock
book_url: https://gum.co/the-nshipster-fake-book
price: 19
number_of_pages: 115
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
date: 2014-06-03
---
================================================
FILE: collections/es/_translators/juan-fernandez-sagasti.md
================================================
---
title: Juan F. Sagasti
name: Juan F. Sagasti
url: https://theam.io
twitter: https://www.twitter.com/jfsagasti
github: https://github.com/jfsagasti
image: juan-fernandez-sagasti.jpg
---
[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.
================================================
FILE: collections/fr/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: Croath Liu
email: Croath.Liu@gmail.com
url: https://twitter.com/cr0ath
twitter: cr0ath
github: croath
image: croath-liu.jpg
---
[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.
================================================
FILE: collections/fr/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[Delisa Mason](https://delisa.me)
([@kattrali](https://twitter.com/kattrali))
is the creator of the Xcode Package Manager,
[Alcatraz](https://alcatraz.io),
as well as a [CocoaPods](https://cocoapods.org) Core Team member.
================================================
FILE: collections/fr/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/fr/_authors/jordan-morgan.md
================================================
---
title: Jordan Morgan
name: Jordan Morgan
email: info@dreaminginbinary.co
url: https://dreaminginbinary.co
twitter: JordanMorgan10
github: JordanMorgan10
image: jordan-morgan.jpg
---
Jordan Morgan is a software developer from Ozark, who created
[Dreaming In Binary](https://dreaminginbinary.co)
as a creative outlet for his side projects.
Currently, he is an iOS engineer at [Buffer](https://buffer.com).
Jordan is focused on helping the community by
doing talks about iOS and remote work and
writing books and blogs posts,
and considers himself a lifelong student for all forms of software engineering.
================================================
FILE: collections/fr/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
google: 106751358503565042647
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
He is the founder of NSHipster and [Flight School](https://flightdotschool.com),
and the creator of several open source libraries,
including [AFNetworking](https://github.com/afnetworking/afnetworking)
and [Alamofire](https://github.com/alamofire/alamofire).
================================================
FILE: collections/fr/_authors/mike-lazer-walker.md
================================================
---
title: Mike Lazer-Walker
name: Mike Lazer-Walker
email: michael@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: mike-lazer-walker.jpg
---
[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).
================================================
FILE: collections/fr/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/fr/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/fr/_books/01-nshipster-swift.md
================================================
---
name: nshipster-swift
title: "NSHipster: Obscure Topics in Cocoa & Swift"
short_title: "NSHipster, Second Edition"
sub_title: "Obscure Topics in Cocoa & Swift"
author: Mattt & Nate Cook
summary: "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."
image: "nshipster-swift-cover@2x.png"
formats:
ebook:
isbn: 978-0-9912182-6-4
availability: in_stock
book_url: https://gum.co/nshipster-swift/
price: 29.00
number_of_pages: 288
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-6-4
date: 2015-04-18
---
================================================
FILE: collections/fr/_books/02-cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: in_stock
book_url: https://gum.co/cfhipsterref
price: 29.00
number_of_pages: 296
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
date: 2014-06-03
---
================================================
FILE: collections/fr/_books/03-nshipster-fake-book-objective-c.md
================================================
---
name: "nshipster-fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
availability: in_stock
book_url: https://gum.co/the-nshipster-fake-book
price: 19
number_of_pages: 115
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
date: 2014-06-03
---
================================================
FILE: collections/fr/_translators/vincent-pradeilles.md
================================================
---
title: Vincent
name: Vincent Pradeilles
twitter: https://www.twitter.com/v_pradeilles
github: https://github.com/vincent-pradeilles
image: vincent-pradeilles.jpg
---
[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.
================================================
FILE: collections/ko/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: Croath Liu
email: Croath.Liu@gmail.com
url: https://twitter.com/cr0ath
twitter: cr0ath
github: croath
image: croath-liu.jpg
---
[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.
================================================
FILE: collections/ko/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[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.
================================================
FILE: collections/ko/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/ko/_authors/jemmons.md
================================================
---
title: "@jemmons"
name: jemmons
url: https://figure.ink
twitter: jemmons
github: jemmons
image: jemmons.jpg
---
Josh ([@jemmons](https://twitter.com/jemmons)) has led mobile development at
graphic.ly, Reverb, and now Retail Zipline.
He lives in Chicago and writes about Swift at [figure.ink](https://figure.ink).
================================================
FILE: collections/ko/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
google: 106751358503565042647
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
He is the founder of NSHipster and [Flight School](https://flightdotschool.com),
and the creator of several open source libraries,
including [AFNetworking](https://github.com/afnetworking/afnetworking)
and [Alamofire](https://github.com/alamofire/alamofire).
================================================
FILE: collections/ko/_authors/mike-lazer-walker.md
================================================
---
title: Mike Lazer-Walker
name: Mike Lazer-Walker
email: michael@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: mike-lazer-walker.jpg
---
[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).
================================================
FILE: collections/ko/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/ko/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/ko/_books/01-nshipster-swift.md
================================================
---
name: nshipster-swift
title: "NSHipster: Obscure Topics in Cocoa & Swift"
short_title: "NSHipster, Second Edition"
sub_title: "Obscure Topics in Cocoa & Swift"
author: Mattt & Nate Cook
summary: "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."
image: "nshipster-swift-cover@2x.png"
formats:
ebook:
isbn: 978-0-9912182-6-4
availability: in_stock
book_url: https://gum.co/nshipster-swift/
price: 29.00
number_of_pages: 288
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-6-4
date: 2015-04-18
---
================================================
FILE: collections/ko/_books/02-cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: in_stock
book_url: https://gum.co/cfhipsterref
price: 29.00
number_of_pages: 296
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
date: 2014-06-03
---
================================================
FILE: collections/ko/_books/03-nshipster-fake-book-objective-c.md
================================================
---
name: "nshipster-fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
availability: in_stock
book_url: https://gum.co/the-nshipster-fake-book
price: 19
number_of_pages: 115
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
date: 2014-06-03
---
================================================
FILE: collections/ko/_translators/pilgwon.md
================================================
---
title: 김필권
name: 김필권
email: rlavlfrnjs12@gmail.com
url: https://blog.pilgwon.app
github: pilgwon
twitter: pilgwon
image: pilgwon.jpg
---
[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).
================================================
FILE: collections/ru/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: Croath Liu
email: Croath.Liu@gmail.com
url: https://twitter.com/cr0ath
twitter: cr0ath
github: croath
image: croath-liu.jpg
---
[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.
================================================
FILE: collections/ru/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[Delisa Mason](https://delisa.me)
([@kattrali](https://twitter.com/kattrali))
is the creator of the Xcode Package Manager,
[Alcatraz](https://alcatraz.io),
as well as a [CocoaPods](https://cocoapods.org) Core Team member.
================================================
FILE: collections/ru/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/ru/_authors/jordan-morgan.md
================================================
---
title: Jordan Morgan
name: Jordan Morgan
email: info@dreaminginbinary.co
url: https://dreaminginbinary.co
twitter: JordanMorgan10
github: JordanMorgan10
image: jordan-morgan.jpg
---
Jordan Morgan is a software developer from Ozark, who created
[Dreaming In Binary](https://dreaminginbinary.co)
as a creative outlet for his side projects.
Currently, he is an iOS engineer at [Buffer](https://buffer.com).
Jordan is focused on helping the community by
doing talks about iOS and remote work and
writing books and blogs posts,
and considers himself a lifelong student for all forms of software engineering.
================================================
FILE: collections/ru/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
google: 106751358503565042647
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
He is the founder of NSHipster and [Flight School](https://flightdotschool.com),
and the creator of several open source libraries,
including [AFNetworking](https://github.com/afnetworking/afnetworking)
and [Alamofire](https://github.com/alamofire/alamofire).
================================================
FILE: collections/ru/_authors/mike-lazer-walker.md
================================================
---
title: Mike Lazer-Walker
name: Mike Lazer-Walker
email: michael@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: mike-lazer-walker.jpg
---
[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).
================================================
FILE: collections/ru/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/ru/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/ru/_books/01-nshipster-swift.md
================================================
---
name: nshipster-swift
title: "NSHipster: Obscure Topics in Cocoa & Swift"
short_title: "NSHipster, Second Edition"
sub_title: "Obscure Topics in Cocoa & Swift"
author: Mattt & Nate Cook
summary: "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."
image: "nshipster-swift-cover@2x.png"
formats:
ebook:
isbn: 978-0-9912182-6-4
availability: in_stock
book_url: https://gum.co/nshipster-swift/
price: 29.00
number_of_pages: 288
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-6-4
date: 2015-04-18
---
================================================
FILE: collections/ru/_books/02-cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: in_stock
book_url: https://gum.co/cfhipsterref
price: 29.00
number_of_pages: 296
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
date: 2014-06-03
---
================================================
FILE: collections/ru/_books/03-nshipster-fake-book-objective-c.md
================================================
---
name: "nshipster-fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
availability: in_stock
book_url: https://gum.co/the-nshipster-fake-book
price: 19
number_of_pages: 115
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
date: 2014-06-03
---
================================================
FILE: collections/zh-Hans/_authors/croath-liu.md
================================================
---
title: Croath Liu
name: "Croath Liu"
email: Croath.Liu@gmail.com
url: https://croath.com
twitter: croath
github: croath
google: 108566152424457191834
image: "croath-liu.jpg"
---
云游四海的工程师
================================================
FILE: collections/zh-Hans/_authors/delisa-mason.md
================================================
---
title: Delisa Mason
name: Delisa Mason
email: delisa.mason@gmail.com
url: https://twitter.com/kattrali
twitter: kattrali
github: kattrali
image: delisa-mason.jpg
---
[Delisa Mason](https://delisa.me)
([@kattrali](https://twitter.com/kattrali))
is the creator of the Xcode Package Manager,
[Alcatraz](https://alcatraz.io),
as well as a [CocoaPods](https://cocoapods.org) Core Team member.
================================================
FILE: collections/zh-Hans/_authors/jack-flintermann.md
================================================
---
title: Jack Flintermann
name: Jack Flintermann
email: jack@stripe.com
url: https://twitter.com/jflinter
twitter: jflinter
github: jflinter
image: jack-flintermann.jpg
---
[Jack Flintermann](https://twitter.com/jflinter) is a software developer at [Stripe](https://stripe.com/). He lives in New York City.
================================================
FILE: collections/zh-Hans/_authors/mattt.md
================================================
---
title: Mattt
name: Mattt
email: mattt@nshipster.com
url: https://twitter.com/mattt
twitter: mattt
github: mattt
google: 106751358503565042647
image: mattt.jpg
---
[Mattt](https://github.com/mattt) ([@mattt](https://twitter.com/mattt))
is a writer and developer in Portland, Oregon.
He is the founder of NSHipster and [Flight School](https://flightdotschool.com),
and the creator of several open source libraries,
including [AFNetworking](https://github.com/afnetworking/afnetworking)
and [Alamofire](https://github.com/alamofire/alamofire).
================================================
FILE: collections/zh-Hans/_authors/mike-lazer-walker.md
================================================
---
title: Mike Lazer-Walker
name: Mike Lazer-Walker
email: michael@lazerwalker.com
url: https://twitter.com/lazerwalker
twitter: lazerwalker
github: lazerwalker
image: mike-lazer-walker.jpg
---
[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).
================================================
FILE: collections/zh-Hans/_authors/natasha-murashev.md
================================================
---
title: Natasha Murashev
name: Natasha Murashev
email: natasha@natashatherobot.com
url: https://twitter.com/NatashaTheRobot
twitter: NatashaTheRobot
github: NatashaTheRobot
image: natasha-murashev.jpg
---
Natasha (aka [@NatashaTheRobot](https://twitter.com/natashatherobot))
is an iOS developer by day and a robot by night.
She organizes the
[try! Swift Conference](https://www.tryswift.co)
around the world.
She's currently living the digital nomad life as her alter identity:
[@NatashaTheNomad](https://twitter.com/natashathenomad).
================================================
FILE: collections/zh-Hans/_authors/nate-cook.md
================================================
---
title: Nate Cook
name: Nate Cook
email: nate@nshipster.com
url: https://twitter.com/nnnnnnnn
twitter: nnnnnnnn
github: natecook1000
image: nate-cook.jpg
---
[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).
================================================
FILE: collections/zh-Hans/_books/01-nshipster-swift.md
================================================
---
name: nshipster-swift
title: "NSHipster: Obscure Topics in Cocoa & Swift"
short_title: "NSHipster, Second Edition"
sub_title: "Obscure Topics in Cocoa & Swift"
author: Mattt & Nate Cook
summary: "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."
image: "nshipster-swift-cover@2x.png"
formats:
ebook:
isbn: 978-0-9912182-6-4
availability: in_stock
book_url: https://gum.co/nshipster-swift/
price: 29
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-6-4
---
================================================
FILE: collections/zh-Hans/_books/02-cfhipsterref.md
================================================
---
name: cfhipsterref
title: "CFHipsterRef: Low-Level Programming on iOS & OS X"
short_title: "CFHipsterRef"
sub_title: "Low-Level Programming on iOS & OS X"
author: Mattt
summary: "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."
image: "cfhipsterref-cover@2x.png"
availability: in_stock
book_url: https://gum.co/cfhipsterref
price: 29.99
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-4-0
---
================================================
FILE: collections/zh-Hans/_books/03-nshipster-fake-book-objective-c.md
================================================
---
name: "nshipster-fake-book-objective-c"
title: "The NSHipster Fake Book (Objective-C)"
author: Mattt
summary: "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."
image: "the-nshipster-fake-book-cover@2x.png"
formats:
pdf:
price: 19.99
isbn: ...
availability: in_stock
book_url: https://gum.co/the-nshipster-fake-book
price: 19.99
category: Media > Books > Non-Fiction > Technology Books
isbn: 978-0-9912182-1-9
---
================================================
FILE: collections/zh-Hans/_translators/Candyan.md
================================================
---
title: Candyan
name: "Candyan"
email: liuyanhp@gmail.com
url: https://candyan.com
github: candyan
---
[Candyan](https://candyan.com) 专业 iOS,业余 Android,偶尔捣鼓下Server的工程师。
================================================
FILE: collections/zh-Hans/_translators/andrew-yang.md
================================================
---
title: Andrew Yang
name: "Andrew Yang"
email: younthu@gmail.com
url: http://blog.ilibrary.me
github: younthu
---
iOS 开发者,11 年之前做过很长时间 windows 后台程序的开发。很喜欢移动应用开发,发布过一些小应用,有一个[个人网站](http://blog.ilibrary.me),你可以尝试和网站上的机器人聊天,希望你不要失望。
================================================
FILE: collections/zh-Hans/_translators/april-peng.md
================================================
---
title: April Peng
name: "April Peng"
email: april.pyl@gmail.com
url: http://aprilme.com
github: aprilnov
---
做 iOS / Mac / Web 开发的大白羊妹子~
================================================
FILE: collections/zh-Hans/_translators/chester-liu.md
================================================
---
title: Chester Liu
name: "Chester Liu"
email: skyline75489@outlook.com
gravatar: 64edfde4a55cef57f9d47d42acbcaf48
github: skyline75489
twitter: ChesterLiu2
---
iOS 工程师,一直想成为更好的自己。我的 [Github](https://github.com/skyline75489) 和 [StackOverflow](https://stackoverflow.com/users/3562486/skyline75489)。
================================================
FILE: collections/zh-Hans/_translators/croath-liu.md
================================================
---
title: Croath Liu
name: "Croath Liu"
email: Croath.Liu@gmail.com
url: https://croath.com
twitter: croath
github: croath
google: 108566152424457191834
gravatar: 720e8ba099f10eca25dd87ef5afe4aa7
---
云游四海的工程师
================================================
FILE: collections/zh-Hans/_translators/david-liu.md
================================================
---
title: David Liu
name: "David Liu"
email: xingruo.liu@gmail.com
twitter: davydliu
github: davydliu
gravatar: 7085efed913ec6d5186e7c57352acfbd
---
混迹于美帝的工程师,户外运动爱好者。
================================================
FILE: collections/zh-Hans/_translators/henry-lee.md
================================================
---
title: Henry Lee
name: "Henry Lee"
email: leelejia@gmail.com
url: http://lejia.li
github: lilejia
gravatar: 97b4cc7deef9a17bef19a13dc2a033a4
---
爱好广泛的 iOS 工程师。
================================================
FILE: collections/zh-Hans/_translators/ricky-tan.md
================================================
---
title: Ricky Tan
name: "Ricky Tan"
email: ricky.tan.xin@gmail.com
url: https://xcoder.tips
gravatar: 71f0bbfbb3b0bc7e6e9aa2187814196a
github: rickytan
google: +rickytanx
---
Ricky 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)。
================================================
FILE: collections/zh-Hans/_translators/steven-wang.md
================================================
---
title: Steven Wang
name: "Steven Wang"
email: mobilefellow@outlook.com
github: mobilefellow
gravatar: d05f1e723ced114014820ed9d9aa42ba
---
iOS 开发者,热爱移动开发,喜欢 Swift 语言。曾经四处漂流,现定居杭州。
================================================
FILE: collections/zh-Hans/_translators/tiny-tian.md
================================================
---
title: change2hao
name: "Tiny Tian"
email: lwtiandev@gmail.com
url: http://devtian.me
gravatar: 5b77b0456447e9040bc35a001b9f3611
twitter: change2hao
github: change2hao
---
iOS开发工程师,爱技术,爱生活。
================================================
FILE: contribute.json
================================================
{
"name": "NSHipster.com",
"description": "A journal of the overlooked bits in Objective-C, Swift, and Cocoa. Updated weekly.",
"repository": {
"url": "https://github.com/nshipster/nshipster.com",
"license": "MIT"
},
"keywords": ["Ruby", "Jekyll"]
}
================================================
FILE: feed.xml
================================================
---
layout: null
---
{{ site.time | date_to_xmlschema }}{{ page.url | absolute_url | xml_escape }}{{ site.title | strip_html | xml_escape | strip }}{{ site.description | markdownify | strip_html }}
{% if site.author %}
{{ site.author.name | default: site.author | xml_escape }}
{% if site.author.email %}
{{ site.author.email | xml_escape }}
{% endif %}
{% if site.author.url %}
{{ site.author.url | absolute_url | xml_escape }}
{% endif %}
{% endif %}
{% assign sorted_posts = site.posts | sort: 'updated_on' | reverse %}
{% for post in sorted_posts limit: 10 %}
{{ post.title | smartify | strip_html | normalize_whitespace | xml_escape }}{{ post.date | date_to_xmlschema }}{{ post.last_revised_on | default: post.date | date_to_xmlschema }}{{ post.id | absolute_url | xml_escape }}
{{ post.content | strip | xml_escape }}
{% assign author = site.authors | where:"name", post.author | first | default: site.author %}
{{ author.name | default: "" | xml_escape }}
{% if author.email %}
{{ author.email | xml_escape }}
{% endif %}
{% if author.url %}
{{ author.url | absolute_url | xml_escape }}
{% endif %}
{% if post.category and post.category != empty %}
{% endif %}
{% for tag in post.tags %}
{% endfor %}
{% if post.excerpt and post.excerpt != empty %}
{{ post.excerpt | markdownify | normalize_whitespace | xml_escape }}
{% endif %}
{% endfor %}
================================================
FILE: flight-school.md
================================================
---
layout: post
date: 2019-02-01
title: Flight School
author: Mattt
category: ""
excerpt: >-
A new book series for advanced Swift developers
from the creators of NSHipster,
with comprehensive guides for Codable, Numbers, and Strings.
Now updated for Swift 5 and available in print.
status:
swift: n/a
---
[Flight School](https://flightdotschool.com)
is a book series for advanced Swift developers
that explores essential topics in iOS and macOS development
through concise, focused guides.
Today, I'm excited to announce updates to our guides to
[Swift Codable](https://flightdotschool.com/books/codable) and
[Numbers](https://flightdotschool.com/books/numbers),
as well as a brand new
[Guide to Swift Strings](https://flightdotschool.com/books/strings).
Everything is up-to-date with the latest from Swift 5 and Xcode 10.2,
and now --- _for the first time_ --- available in print!
If you like NSHipster and are looking for something a bit longer,
I think you're gonna love what Flight School has to offer.
---
{% if site.lang == "en-US" %}
{::nomarkdown type="html"}
{% include book.html book="flight-school-guide-to-swift-codable" %}
{% include book.html book="flight-school-guide-to-swift-numbers" %}
{% include book.html book="flight-school-guide-to-swift-strings" %}
{:/}
{% endif %}
## Why I'm Writing Flight School
As software developers,
our jobs require us to learn a variety of different
platforms, programming languages, frameworks, and tools.
In spite of their differences,
most technologies share a common foundation in concepts
like floating-point arithmetic, data interchange, and string encoding ---
the kinds of things you might find in a typical
Computer Science curriculum.
But for those of us who came into programming from unconventional backgrounds,
(for instance, I studied philosophy and linguistics as an undergraduate),
the weight of all of this can feel overwhelming at times.
And even if you did study CS in college,
it may be hard to relate the theory of your coursework
(what you can remember of it, anyway)
to the realities of your day job.
I'm writing [Flight School](https://flightdotschool.com)
to explore important concepts in software development
in a way that's informative, accessible, and entertaining.
Each book is short enough to be read over a weekend
(or perhaps coffee breaks over the course of a work week).
Each chapter is filled with practical information that's backed by examples
that you can experiment with for yourself in Xcode Playgrounds.
The forthcoming [_Guide to Strings_](https://flightdotschool.com/books/strings)
is our newest and most ambitious release yet,
covering everything from the Unicode® standard and Swift 5 `String` internals
to binary-to-text encoding, parser generators, and natural language processing.
If you've ever felt like you wanted to get a handle on text _once and for all_,
this is the book for you.
It'll be available to download next Friday, February 8th,
and you can pre-order a copy for yourself and download a sample chapter now.
---
The response from Flight School readers since launching earlier last year
has been overwhelming,
and I couldn't be more excited to share this with everyone.
I look forward to continuing to share new and interesting things
on NSHipster and Flight School,
and thank you for your continued support. 🧡
================================================
FILE: index.html
================================================
---
title: NSHipster
permalink: /
---
{% assign sorted_posts = site.posts | sort: 'updated_on' | reverse %}
{% assign latest_post = sorted_posts.first %}
{% endif %}
{% for group in site.groups %}
{% for category in site.categories %}
{% assign category_name = category[0] %}
{% if category_name != group %}
{% continue %}
{% endif %}
{{ category_name | default: "Miscellaneous" }}
{% for posts in category offset: 1 %}
{% assign sorted = posts | sort: "title" %}
{% for post in sorted %}
{% unless post.retired %}
{% endfor %}
{% endfor %}
================================================
FILE: return.md
================================================
---
layout: post
date: 2018-07-09
title: Returning to Our Regularly Scheduled Programming
author: Mattt
category: ""
retired: true
excerpt: NSHipster returns to weekly publication,
with new articles every Monday,
updates every Wednesday,
and new trivia questions every Friday.
status:
swift: n/a
---
When the iPhone SDK first came out,
there was a disconnect between how futuristic the iPhone was
and how, well... _not_ Objective-C was.
For many new developers,
Objective-C was seen as an ugly, obscure language ---
something you merely put up with
in exchange for the privilege of developing on this amazing new platform.
That was certainly the case for me when I wrote my first app.
But over time,
I learned to appreciate the beauty of the language and its frameworks.
I started NSHipster in July 2012
as a way to share my newfound passion.
At the time,
the term "hipster" was tossed around frequently as a casual pejorative
for people who ironically enjoyed obscure or bad things.
What better term for someone excited about Objective-C, right?
Rather than being ashamed or annoyed by the language we used in our day-to-day,
it felt good to turn it around and say
"Oh, this? It's an obscure API. You've probably never heard of it."
---
Today marks six years since I first launched NSHipster
(which is a big milestone for all of you out there counting in
[base-6](https://www.seximal.net)).
To mark the occasion,
I'm very excited to announce my return as the managing editor of NSHipster.
I'm extremely thankful to [Nate Cook](https://nshipster.com/authors/nate-cook/)
for his stewardship of NSHipster.
During my tenure at Apple from 2015 to 2018,
I was unable to contribute to the site;
it's entirely thanks to him that NSHipster exists today.
His contributions to Swift are extraordinary and immeasurable,
and we all benefit immensely as a community from his work.
## What to Expect
**NSHipster is a celebration of small details
that come from big ideas.**
It stands at that fabled intersection of liberal arts and technology,
where we can collectively geek out about
thoughtful abstractions and clever optimizations.
Our focus will continue to be Objective-C and Swift,
and Apple platforms like macOS and iOS.
And we'll also look at any other languages or technologies
that can help us make insanely great software.
But most importantly,
we'll be returning to a regular publishing schedule.
Here's what that will look like:
### New Articles Every Monday
Every Monday,
I want you to be able to visit the site
(or refresh your feed reader)
and learn something new.
It could be topical and directly applicable to what you're working on right now.
It might be something you hadn't heard of before, and decide to research further.
Or maybe its a different way of thinking about a problem.
We'll start this week with an article
that ostensibly falls into any of those three categories:
[Swift GYB](https://nshipster.com/swift-gyb/)
> This time around,
> I'd like to open things up more for external contributors.
> If you have a topic that you'd like to write about on NSHipster,
> please submit a quick, 3–5 sentence, pitch to
> [mattt@nshipster.com](mailto:mattt@nshipster.com).
### Updated Articles Every Wednesday
With nearly 150 articles dating as far back as 2012,
there's a lot of material on NSHipster that needs to be revisited.
Out of date, sample code (mostly Swift),
changes in behavior that impact the documentation,
entirely new APIs that need to be addressed...
We'll have updates every Wednesday
until we run out of outdated material (😂).
### Trivia Questions Every Friday
The annual NSHipster pub quizzes at WWDC
was one of our favorite events of the year.
Hundreds of developers came out and formed small teams
(with hilarious team names)
to answer trivia questions about APIs, language features, and Apple lore.
For example, here's one of the tougher question
from the [last quiz we did](https://nshipster.com/nshipster-quiz-8/):
---
**Question**: After Chris Lattner,
who was the second contributor to Swift?
{::nomarkdown}
Answer
{:/}
---
We're excited to make these kinds of trivia questions a regular feature
and share them with everyone.
[Follow us on Twitter](https://twitter.com/nshipster)
to take our weekly NSHipster quiz.
## What's Different Right Now
You might have noticed a few changes since your last visit.
Here's a recap of what we've been working on for today's announcement:
### Upgraded Site Infrastructure
A lot's changed about the internet since NSHipster first launched.
The web is significantly faster and more secure,
thanks to new standards like HTTP/2
and the widespread adoption of SSL.
In the weeks leading up to today's relaunch,
I quietly got to work upgrading NSHipster's tech stack:
- Both [NSHipster.com](https://nshipster.com)
and [NSHipster.cn](https://nshipster.cn)
are now hosted by [Netlify](https://www.netlify.com),
which has been an absolute joy to use.
Everything is served from a global CDN
(using HTTP/2 if your browser supports it)
to ensure that the site loads fast, no matter where you are.
- NSHipster is now served exclusively using HTTPS
thanks to [Let's Encrypt](https://letsencrypt.org).
- Server responses now include fancy new security headers like
[Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) and
[Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security).
- All of the image assets were re-optimized with the latest version of
[ImageOptim](https://imageoptim.com/mac),
which reduced file size by ~30% across the board.
- Critical CSS is now inlined to optimize the site's
[Critical Rendering Path](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/).
- And most important of all,
the site now
[supports the iPhone X notch](https://webkit.org/blog/7929/designing-websites-for-iphone-x/).
If you notice anything amiss,
like a missing image
or a page that isn't rendering as you expected,
please [let us know](https://github.com/nshipster/nshipster.com)!
### Removed Site Search
In the process of upgrading the site's infrastructure,
I ended up removing the search widget provided by
[Swiftype](https://swiftype.com).
I'm looking into a couple alternatives,
but don't currently have any specific plans for bringing site search back.
### Retired Content
Technology evolves quickly.
And while I've tried to write mostly evergreen content on NSHipster,
there are some articles that have become obsolete.
For example, our article about [BackRow](https://nshipster.com/backrow/)
is irrelevant now that the tvOS is available.
These articles will live on in perpetuity at their original URLs,
but they'll include a deprecation notice at the top
and won't be displayed in the main site navigation.
## More Things to Look Forward To
But that's not all ---
in addition to new weekly articles,
we have a lot of exciting things in the works:
### CFHipsterRef Update and Print Edition
[CFHipsterRef](https://gum.co/cfhipsterref)
was released
on the eve of Swift's announcement at WWDC 2014.
Although this new language
gets most of our attention these days
(what, with its cool name and fast bird logo),
Objective-C and low-level technologies
are still just as important as ever.
Coming this fall,
we'll be releasing a second edition CFHipsterRef
with new and updated content.
This will be a free update to everyone who ordered the first edition.
(I also look forward to finally making good on a promise I made
to release a print edition of the book)
### New Books
I can't say too much yet,
but I'm planning to have a something out by the end of the year.
Stay tuned!
> In the meantime,
> check out [Flight School](https://flightdotschool.com).
> It's a new, ongoing book series I'm working on
> that's all about Swift.
> Each book offers an in-depth look at essential topics
> for intermediate and advanced developers.
>
> The first two books,
> [Guide to Swift Codable](https://gumroad.com/l/codable)
> and [Guide to Swift Numbers](https://gumroad.com/l/swift-numbers),
> are both available for download,
> with more on the way soon.
### More Tools and Experiments
NSHipster is more than writing blog posts and books.
It's also an opportunity to make fun and useful things
for the community.
One such project is
[ASCIIwwdc](https://asciiwwdc.com),
a site that offers searchable transcripts of WWDC sessions
going back to 2010.
It was recently updated with all of the sessions from 2017
and most from 2018,
so if you haven't gotten around to watching this year's talks,
you might find this to be a nice way to get up to speed quickly.
Another example is
[SwiftDoc](https://swiftdoc.org).
Nate created this around the time that he took the reigns of NSHipster,
and it's been an invaluable tool for understanding
the complex type relationships in the Swift standard library.
I've updated the site for Swift 4.2,
and look forward to keeping it in sync going forward.
Look out for more of these in the future!
### Conferences and Meetups Near You
This fall,
I'll have the honor of presenting at
some of the best developer conferences of the year,
in New York City, Logroño, Madrid, and Paris:
- [try! Swift NYC](https://www.tryswift.co/events/2018/nyc/) • New York City, USA • September 4th & 5th
- [NSSpain](https://2018.nsspain.com) • Logroño, Spain • September 12th – 14th
- NSCoders Night • Madrid, Spain • September 11th
- [FrenchKit](https://frenchkit.fr) • Paris, France • September 20th & 21st
If you plan on attending any of these
or will be in any of these cities when I'm there,
[please get in touch](https://twitter.com/mattt) (my DMs are open).
---
Thank you to everyone who's supported NSHipster over the past 6 years.
We couldn't be more excited about what's to come.
Until next time:
May your code continue to compile and inspire.
================================================
FILE: sitemap.xml
================================================
---
layout: null
---
{{ site.url }}{{ site.posts.first.date | date_to_xmlschema }}daily1.0
{% for post in site.posts %}
{% unless post.retired %}
{{ post.url | absolute_url }}{{ post.updated_on | date_to_xmlschema }}yearly0.9
{% endunless %}
{% endfor %}
{% for author in site.authors %}
{{ author.url | absolute_url }}
{% endfor %}
{% for translator in site.translators %}
{{ translator.url | absolute_url }}
{% endfor %}
================================================
FILE: status.md
================================================
---
layout: page
title: Article Status
permalink: /status
retired: true
---
The common swift (_Apus apus_) can travel at speeds over 100km/h.
The Swift programming language ---
true to its name and namesake ---
is similarly fast-moving,
frequently introducing new language features and syntax rules.
As a result,
some of our articles may become incorrect or outdated over time.
We do our best to keep things fresh,
with new updates to existing articles made every week,
and invite you to help us find and correct any mistakes you find by
[opening a new issue on our GitHub repository](https://github.com/NSHipster/articles/issues/new).
In the meantime,
please consult the table below
for guidance on when each of our articles was last updated,
and which version of Swift it's targeting:
"t.b.c." indicates that an article has not yet been translated to Swift
"n/a" notes that a Swift translation would not be useful or appropriate.
Article
Swift Version
Last Review
{% assign sorted = site.posts | sort: 'title' %}
{% for post in sorted %}
================================================
FILE: vendor/cache/twitter_cldr-6.7.0.gem
================================================
[File too large to display: 15.8 MB]