{"id":18333297,"url":"https://github.com/usami-k/webswiftplayground","last_synced_at":"2026-05-01T19:34:19.806Z","repository":{"id":75556654,"uuid":"411137061","full_name":"usami-k/WebSwiftPlayground","owner":"usami-k","description":"iOSDC Japan 2021 のパンフレット記事「Webブラウザで動くSwift Playgroundを作ろう」を実際にやってみた","archived":false,"fork":false,"pushed_at":"2021-09-29T04:23:15.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-04-09T18:58:26.818Z","etag":null,"topics":["bootstrap","swift","vapor"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/usami-k.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-28T04:30:37.000Z","updated_at":"2021-09-29T08:18:55.000Z","dependencies_parsed_at":"2023-06-06T21:30:19.206Z","dependency_job_id":null,"html_url":"https://github.com/usami-k/WebSwiftPlayground","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/usami-k/WebSwiftPlayground","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usami-k%2FWebSwiftPlayground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usami-k%2FWebSwiftPlayground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usami-k%2FWebSwiftPlayground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usami-k%2FWebSwiftPlayground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usami-k","download_url":"https://codeload.github.com/usami-k/WebSwiftPlayground/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usami-k%2FWebSwiftPlayground/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32510808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bootstrap","swift","vapor"],"created_at":"2024-11-05T19:41:49.874Z","updated_at":"2026-05-01T19:34:19.788Z","avatar_url":"https://github.com/usami-k.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Web Swift Playground\n\niOSDC Japan 2021 のパンフレット記事「[Webブラウザで動くSwift Playgroundを作ろう](https://fortee.jp/iosdc-japan-2021/proposal/f3342cf9-6d11-4693-b219-5b2c2b8b4ffd)」を実際にやってみた。\n\n## はじめに\n\n- 多くのプログラミング言語にはWebで動作するPlaygroundが提供されている。\n- Swiftには公式のWeb Playgroundが提供されていない。\n- サーバーサイドSwiftとWebプログラミングの技術を使って自分で作れる。\n\n## MVP (Minimum Viable Product)\n\n- 不特定多数が使うWebサービスを公開する、となるととても大変。\n- ローカル環境でアクセスできるWebアプリケーションを作る。\n\n## WebのUIを作る\n\n- Webアプリケーションの世界にもUIフレームワークがある。\n- 基本設計\n    - 画面を左右に2分割する。コードエディタと結果表示。\n    - コードを実行するRunボタンを置く。\n- フレームワーク\n    - TwitterのBootstrapを使用する。\n\n### レイアウト\n\n- `index.html`を作って、BootstrapのStarter Templateをコピーペースト。\n    - [Getting Started](https://getbootstrap.com/docs/5.1/getting-started/introduction/)から。\n- 記事のコードになるよう`title`と`body`を変更。\n- ブラウザで表示確認。\n\n### コードエディタ\n\n- Swiftのシンタックスハイライトに対応したエディタコンポーネントを置く。\n    - Ace：とっつきやすい。今回はこれを使う。\n    - CodeMirror：バージョンアップで仕組みが変わったので注意。\n    - Monaco Editor：高機能。やや難しい。\n- エディタコンポーネントのロード。\n    - ライブラリはCDN経由で配布されている。\n    - [Embedding Ace in Your Site](https://ace.c9.io/#nav=embedding)のcdnjsからコピーペースト。\n- エディタコンポーネントを配置。\n    - 記事のコードのとおり。\n- ブラウザで表示確認。\n\n### 結果表示\n\n- ターミナル風に表示するコンポーネントを置く。\n    - Xterm.jsを使う。\n- コンポーネントのロード。\n    - [xterm CDN by jsDelivr](https://www.jsdelivr.com/package/npm/xterm)を使う。\n    - 上記サイトのcssフォルダをクリックすると`xterm.css`が表示されるので、そこからコピーペースト。\n    - `xterm.min.js`も同様にコピーペースト。\n- コンポーネントを配置。\n    - 記事のコードのとおり。\n- ブラウザで表示確認。\n\n## バックエンドのAPIを実装する\n\n- バックエンド\n    - コードエディタに入力されたコードを受け取り、実行結果を返す。\n- 言語\n    - サーバーサイドSwift\n- フレームワーク\n    - Vapor\n    - 他はメンテナンスが停止しており、現在は事実上唯一の選択肢。\n\n### プロジェクト作成\n\n- VaporのCLIツールをインストール（Homebrew）。\n- Vaporプロジェクト作成、Xcodeで開く。\n    - [Hello, world](https://docs.vapor.codes/4.0/hello-world/)のとおり。\n    - 依存するSwift Packageのダウンロードが行われるので待つこと。\n- `routes.swift`を記事のコードのとおり実装する。\n    - POSTで受け取ったコードを実行して標準出力に出すもの。\n- Xcodeでビルド、実行。\n- cURLで動作確認。\n    - `curl -X POST \"http://localhost:8080/run\" -H 'Content-Type:application/json' --data '{\"code\":\"print(\\\"Hello World!\\\")\"}'`\n\n### フロントエンドとの結合\n\n- 記事では、GitHubのサンプルコードを参照とのこと。\n    - https://github.com/kishikawakatsumi/swift-online-playground-tutorial\n- 結合手順\n    - バックエンド\n        - POSTに対して、JSONでレスポンスを返す。\n        - localhostに接続したときに`index.html`の内容を返す。\n    - フロントエンド\n        - Runボタンで入力コードをPOSTして、レスポンスで受け取った出力内容を表示する。\n\n### JSONレスポンス\n\n- `routes.swift`\n    - POSTで返す型を`String`でなく`Content`準拠の型にする。\n- cURLで動作確認。\n    - JSONが返ってくればOK。\n\n### HTMLを返す\n\n- `Public`ディレクトリを作って`index.html`をそこに入れる。\n- `configure.swift`\n    - `Public`ディレクトリを使う。\n- `routes.swift`\n    - GETに対して`index.html`を返す。\n- 動作確認\n    - Xcodeではなく`swift run`で実行する。\n    - ブラウザで`http://localhost:8080`を開く。\n    - フロントエンドが表示できればOK。\n\n### フロントエンドの対応\n\n- `index.html`\n    - Runボタンの処理をする`script`タグを追加する。\n    - エディタの内容をPOSTする。\n    - レスポンスから出力結果を取り出して結果表示エリアに出す。\n- 動作確認\n    - Xcodeではなく`swift run`で実行する。\n    - ブラウザで`http://localhost:8080`を開く。\n    - Swiftコードを書いてRunボタンを押し、結果が表示されればOK。\n\n## サンドボックスで実行する\n\n- 任意のコードが実行できるので公開しては危険。\n- 実行環境を使い捨てのコンテナに閉じ込める。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusami-k%2Fwebswiftplayground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusami-k%2Fwebswiftplayground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusami-k%2Fwebswiftplayground/lists"}