Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,16 @@ jobs:
xcode: ${{ matrix.xcode }}
- name: Run Unit Tests
run: swift test

site-build:
name: Site Build
runs-on: macos-15
steps:
- uses: actions/checkout@v6
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Build site
run: bundle exec rake site:build
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually deploying the site? Or just validating that it builds successfully? My guess it that it's just validating the build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is validating that it builds. We'll need to add a separate workflow for deployment.

env:
JEKYLL_ENV: production
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.build
.swiftpm
.DS_Store
.vscode
.vscode

# The site generated by Jekyll.
_site
7 changes: 4 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
source 'https://rubygems.org' do
gem "rake", "~> 13.0.0"
end
source 'https://rubygems.org'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworked this file to address this warning from Bundler:

[DEPRECATED] This Gemfile does not include an explicit global source. Not using an explicit global source may result in a different lockfile being generated depending on the gems you have installed locally before bundler is run. Instead, define a global source in your Gemfile like this: source "https://rubygems.org".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!


gem "rake", "~> 13.0.0"
gem "jekyll", "~> 4.4.1"
80 changes: 76 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,17 +1,89 @@
GEM
specs:

GEM
remote: https://rubygems.org/
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.3.0)
bigdecimal (3.3.1)
colorator (1.1.0)
concurrent-ruby (1.3.5)
csv (3.3.5)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.17.2)
ffi (1.17.2-arm64-darwin)
forwardable-extended (2.6.0)
google-protobuf (4.33.1)
bigdecimal
rake (>= 13)
google-protobuf (4.33.1-arm64-darwin)
bigdecimal
rake (>= 13)
http_parser.rb (0.8.0)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
jekyll (4.4.1)
addressable (~> 2.4)
base64 (~> 0.2)
colorator (~> 1.0)
csv (~> 3.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (>= 2.0, < 4.0)
jekyll-watch (~> 2.0)
json (~> 2.6)
kramdown (~> 2.3, >= 2.3.1)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (~> 0.3, >= 0.3.6)
pathutil (~> 0.9)
rouge (>= 3.0, < 5.0)
safe_yaml (~> 1.0)
terminal-table (>= 1.8, < 4.0)
webrick (~> 1.7)
jekyll-sass-converter (3.1.0)
sass-embedded (~> 1.75)
jekyll-watch (2.2.1)
listen (~> 3.0)
json (2.16.0)
kramdown (2.5.1)
rexml (>= 3.3.9)
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (6.0.2)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.4.4)
rouge (4.6.1)
safe_yaml (1.0.5)
sass-embedded (1.94.2)
google-protobuf (~> 4.31)
rake (>= 13)
sass-embedded (1.94.2-arm64-darwin)
google-protobuf (~> 4.31)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.6.0)
webrick (1.9.1)

PLATFORMS
arm64-darwin-23
ruby

DEPENDENCIES
rake (~> 13.0.0)!
jekyll (~> 4.4.1)
rake (~> 13.0.0)

BUNDLED WITH
2.5.4
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
]
```

</details>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that some details closing tags were missing.


* <a id='long-typealias'></a>(<a href='#long-typealias'>link</a>) [Long](https://github.com/airbnb/swift#column-width) type aliases of protocol compositions should wrap before the `=` and before each individual `&`. [![SwiftFormat: wrapArguments](https://img.shields.io/badge/SwiftFormat-wrapArguments-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#wrapArguments)

<details>
Expand Down Expand Up @@ -1084,6 +1086,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
& UniverseSimulatorServiceProviding
```

</details>

* <a id='sort-typealiases'></a>(<a href='#sort-typealiases'>link</a>) **Sort protocol composition type aliases alphabetically.** [![SwiftFormat: sortTypealiases](https://img.shields.io/badge/SwiftFormat-sortTypealiases-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#sortTypealiases)

<details>
Expand All @@ -1110,6 +1114,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
& UniverseSimulatorServiceProviding
```

</details>

* <a id='prefer-if-let-shorthand'></a>(<a href='#prefer-if-let-shorthand'>link</a>) Omit the right-hand side of the expression when unwrapping an optional property to a non-optional property with the same name. [![SwiftFormat: redundantOptionalBinding](https://img.shields.io/badge/SwiftFormat-redundantOptionalBinding-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#redundantOptionalBinding)

<details>
Expand Down Expand Up @@ -1142,6 +1148,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
else { … }
```

</details>

* <a id='else-on-same-line'></a>(<a href='#else-on-same-line'>link</a>) **Else statements should start on the same line as the previous condition's closing brace, unless the conditions are separated by a blank line or comments.** [![SwiftFormat: elseOnSameLine](https://img.shields.io/badge/SwiftFormat-elseOnSameLine-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#elseOnSameLine)

<details>
Expand Down Expand Up @@ -1196,6 +1204,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='multi-line-conditions'></a>(<a href='#multi-line-conditions'>link</a>) **Multi-line conditional statements should break after the leading keyword.** Indent each individual statement by [2 spaces](https://github.com/airbnb/swift#spaces-over-tabs). [![SwiftFormat: wrapArguments](https://img.shields.io/badge/SwiftFormat-wrapArguments-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#wrapArguments)

<details>
Expand Down Expand Up @@ -1609,6 +1619,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='indent-multiline-string-literals'></a>(<a href='#indent-multiline-string-literals'>link</a>) **Indent the body and closing triple-quote of multiline string literals**, unless the string literal begins on its own line in which case the string literal contents and closing triple-quote should have the same indentation as the opening triple-quote. [![SwiftFormat: indent](https://img.shields.io/badge/SwiftFormat-indent-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#indent)

<details>
Expand Down Expand Up @@ -1779,6 +1791,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='no-spaces-around-function-parens'></a>(<a href='#no-spaces-around-parens'>link</a>) For function calls and declarations, there should be no spaces before or inside the parentheses of the argument list. [![SwiftFormat: spaceInsideParens](https://img.shields.io/badge/SwiftFormat-spaceInsideParens-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#spaceInsideParens) [![SwiftFormat: spaceAroundParens](https://img.shields.io/badge/SwiftFormat-spaceAroundParens-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#spaceAroundParens)

<details>
Expand Down Expand Up @@ -3010,6 +3024,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='avoid-global-functions'></a>(<a href='#avoid-global-functions'>link</a>) **Avoid global functions whenever possible.** Prefer methods within type definitions.

<details>
Expand Down Expand Up @@ -4694,6 +4710,8 @@ _You can enable the following settings in Xcode by running [this script](resourc
}
```

</details>

* <a id='prefer-throwing-tests'></a>(<a href='#prefer-throwing-tests'>link</a>) **Prefer throwing tests to `try!`**. `try!` will crash your test suite like a force-unwrapped optional. XCTest and Swift Testing support throwing test methods, so use that instead. [![SwiftFormat: noForceTryInTests](https://img.shields.io/badge/SwiftFormat-noForceTryInTests-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#noForceTryInTests)

<details>
Expand Down
37 changes: 33 additions & 4 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,55 @@ namespace :update do
temp_dir = Dir.mktmpdir
artifact_bundle_url = "https://github.com/calda/SwiftFormat-nightly/releases/download/#{latest_version_number}/swiftformat.artifactbundle.zip"
artifact_bundle_zip_path = "#{temp_dir}/swiftformat.artifactbundle.zip"

sh "curl #{artifact_bundle_url} -L --output #{artifact_bundle_zip_path}"
checksum = `swift package compute-checksum #{artifact_bundle_zip_path}`

# Update the Package.swift file to reference this version
package_manifest_path = 'Package.swift'
package_manifest_content = File.read(package_manifest_path)

updated_swift_format_reference = <<-EOS
.binaryTarget(
name: "swiftformat",
url: "https://github.com/calda/SwiftFormat-nightly/releases/download/#{latest_version_number}/SwiftFormat.artifactbundle.zip",
checksum: "#{checksum.strip}"
),
EOS

regex = /[ ]*.binaryTarget\([\S\s]*name: "swiftformat"[\S\s]*?\),\s/
updated_package_manifest = package_manifest_content.gsub(regex, updated_swift_format_reference)
File.open(package_manifest_path, "w") { |file| file.puts updated_package_manifest }

puts "Updated Package.swift to reference SwiftFormat #{latest_version_number}"
end
end

namespace :site do
desc 'Prints the README content used to build the site'
task :filter_readme do
require_relative 'site/site_content'
puts SiteContent.new.filter_readme
end

desc 'Prepares index.md and syntax highlighting assets'
task :prepare do
require_relative 'site/site_content'
puts '📋 Generating index.md from README.md with frontmatter...'
SiteContent.new.write_index
puts '🎨 Generating syntax highlighting CSS...'
SiteContent.new.generate_syntax_css
end

desc 'Builds the static site into _site/'
task build: :prepare do
env = { 'JEKYLL_ENV' => ENV.fetch('JEKYLL_ENV', 'production') }
sh env, 'bundle exec jekyll build --source site/src'
end

desc 'Serves the site to support previewing its content during development'
task serve: :prepare do
env = { 'JEKYLL_ENV' => 'development' }
sh env, 'bundle exec jekyll serve --source site/src'
end
Comment on lines +57 to +83
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would you run these commands? Do they have to be ran manually each time we make content changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for asking. I clarified two of the commands in #339. site:build is mostly for CI validation.

end
3 changes: 3 additions & 0 deletions site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# These site source files are generated.
src/index.md
src/assets/css/syntax.css
11 changes: 11 additions & 0 deletions site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Website

## Local development

To start the local development server, run the following command:

```bash
bundle exec rake site:serve
```

Once the server is running, open [http://localhost:4000](http://localhost:4000) in your browser to preview the site.
76 changes: 76 additions & 0 deletions site/site_content.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true

require 'open3'

class SiteContent
attr_reader :readme_path, :index_path, :syntax_css_path

def initialize()
site_dir = File.expand_path('src', __dir__)
@readme_path = File.expand_path('../README.md', __dir__)
@index_path = File.join(site_dir, 'index.md')
@syntax_css_path = File.join(site_dir, 'assets/css/syntax.css')
end

def filter_readme
(filter_readme_lines + ['']).join("\n")
end

# Write index.md file.
def write_index
File.write(index_path, generate_front_matter + filter_readme)
end

# Write syntax.css file.
def generate_syntax_css
stdout, stderr, status = Open3.capture3('bundle', 'exec', 'rougify', 'style', 'github.light')
raise "rougify failed:\n#{stderr}" unless status.success?

File.write(syntax_css_path, stdout)
end

private

def generate_front_matter
<<~FRONT
---
layout: default
---

FRONT
end

def filter_readme_lines
lines = File.readlines(readme_path, chomp: true)
filtered = []
skip_plugin_section = false
skip_amendments_section = false

lines.each do |line|
# Exclude the SPM command plugin section from the site.
if line.start_with?('## Swift Package Manager command plugin')
skip_plugin_section = true
next
elsif skip_plugin_section
skip_plugin_section = false if line.start_with?('## ')
next if skip_plugin_section
end

if line.start_with?('## Amendments')
skip_amendments_section = true
next
elsif skip_amendments_section
skip_amendments_section = false if line.start_with?('** ')
next if skip_amendments_section
end

# Exclude the badges from the site.
stripped = line.strip
next if stripped.start_with?('[![](') && stripped.include?('swiftpackageindex.com')

filtered << line.rstrip
end

filtered
end
end
6 changes: 6 additions & 0 deletions site/src/_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
title: Airbnb Swift Style Guide
github_url: https://github.com/airbnb/swift
markdown: kramdown
kramdown:
input: GFM
parse_block_html: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was necessary for the code blocks to render correctly.

16 changes: 16 additions & 0 deletions site/src/_layouts/default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to put files that are inputs into the site under a src/ subdirectory to avoid needing to manage excludes in the _config.yml file. In this way, only files under src/ will be used to generate the site.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.title | default: site.title }}</title>
<link rel="stylesheet" href="{{ '/assets/css/syntax.css' | relative_url }}">
<link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}">
</head>
<body>
{{ content }}
<footer>
<a href="{{ site.github_url }}">View on GitHub</a>
</footer>
</body>
</html>
Loading
Loading