├── .dockerignore
├── .editorconfig
├── .github
└── main.workflow
├── .gitignore
├── Benchmarking
├── query.json
└── vegeta.txt
├── Frontend
├── GraphQL
│ └── graphql-playground.leaf
├── Helpers
│ ├── easymde-factory.leaf
│ └── fields-markdown-conversion.leaf
├── Posts
│ ├── create-post.leaf
│ ├── edit-post.leaf
│ ├── post-fields.leaf
│ └── posts.leaf
├── Settings
│ └── settings.leaf
├── Types
│ ├── create-type.leaf
│ ├── edit-type.leaf
│ ├── type-fields.leaf
│ └── types.leaf
├── Users
│ ├── create-user.leaf
│ ├── login.leaf
│ ├── register-fields.leaf
│ ├── register.leaf
│ └── users.leaf
├── errors.leaf
├── footer.leaf
├── header.leaf
├── index.leaf
├── links-administration.leaf
├── links-content.leaf
├── modal.leaf
└── nav.leaf
├── LICENSE
├── Package.resolved
├── Package.swift
├── Public
├── .gitkeep
├── fonts
│ ├── Inter-UI-Bold.woff
│ ├── Inter-UI-Bold.woff2
│ ├── Inter-UI-Regular.woff
│ └── Inter-UI-Regular.woff2
├── images
│ ├── add.svg
│ ├── check.svg
│ ├── key.svg
│ ├── name.svg
│ ├── pigeon.svg
│ ├── remove.svg
│ ├── sign-in.svg
│ └── username.svg
└── styles
│ └── style.css
├── README.md
├── Sources
├── App
│ ├── Configuration
│ │ ├── CMSSettings.swift
│ │ └── SettingsService.swift
│ ├── Controllers
│ │ ├── ContentTypeController.swift
│ │ ├── GraphQLController.swift
│ │ ├── JSONController.swift
│ │ ├── PigeonController.swift
│ │ ├── PostController.swift
│ │ ├── RootViewController.swift
│ │ ├── SettingsController.swift
│ │ └── UserController.swift
│ ├── Leaf
│ │ ├── DateTimeZoneFormat.swift
│ │ └── JSEscapedFormat.swift
│ ├── Models
│ │ ├── ContentCategory+GraphQL.swift
│ │ ├── ContentCategory.swift
│ │ ├── ContentField.swift
│ │ ├── ContentItem.swift
│ │ ├── ContentState.swift
│ │ ├── GraphQLTypes.swift
│ │ ├── Markdown.swift
│ │ ├── SupportedType.swift
│ │ ├── SupportedValue.swift
│ │ └── User.swift
│ ├── Utilities
│ │ ├── DateFormatter.swift
│ │ ├── GraphQL.swift
│ │ └── String.swift
│ ├── Views
│ │ ├── Index.swift
│ │ ├── Login.swift
│ │ ├── Settings.swift
│ │ ├── SharedPageComponents.swift
│ │ ├── Types.swift
│ │ └── Users.swift
│ ├── app.swift
│ ├── boot.swift
│ ├── configure.swift
│ └── routes.swift
└── Run
│ └── main.swift
├── benchmark.sh
└── ui.sketch
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .build
3 | DerivedData
4 | Package.resolved
5 | *.xcodeproj
6 |
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | indent_size = 2
6 | charset = utf-8
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.swift]
12 | indent_style = space
13 | indent_size = 4
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.github/main.workflow:
--------------------------------------------------------------------------------
1 | workflow "Lint" {
2 | on = "pull_request"
3 | resolves = ["swiftlint"]
4 | }
5 |
6 | action "swiftlint" {
7 | uses = "norio-nomura/action-swiftlint@master"
8 | secrets = ["GITHUB_TOKEN"]
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Packages
2 | Package.pins
3 | .build
4 | xcuserdata
5 | *.xcodeproj
6 | DerivedData/
7 | .DS_Store
8 | timeline.xctimeline
9 | playground.xcworkspace
10 |
--------------------------------------------------------------------------------
/Benchmarking/query.json:
--------------------------------------------------------------------------------
1 | {"query":"{\n tests {\n nodes {\n title\n meta {\n published\n }\n }\n }\n}\n"}
2 |
--------------------------------------------------------------------------------
/Benchmarking/vegeta.txt:
--------------------------------------------------------------------------------
1 | POST http://localhost:8080/graphql
2 | Content-Type: application/json
3 | @./query.json
4 |
--------------------------------------------------------------------------------
/Frontend/GraphQL/graphql-playground.leaf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
6 |
7 | #embed("Posts/post-fields")
8 |
9 |
10 | #embed("footer")
11 |
12 |
13 |
81 |
--------------------------------------------------------------------------------
/Frontend/Posts/edit-post.leaf:
--------------------------------------------------------------------------------
1 | #embed("header")
2 | #embed("nav")
3 | #embed("modal")
4 |
7 |
8 | #embed("Posts/post-fields")
9 |
10 | Authors
11 |
12 | #for(user in shared.users) {
13 |
14 | #(user.name)
15 |
23 |
24 | }
25 |
26 |
27 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
156 | #embed("footer")
157 |
--------------------------------------------------------------------------------
/Frontend/Posts/post-fields.leaf:
--------------------------------------------------------------------------------
1 | #embed("errors")
2 |
3 |
10 |
11 | #embed("errors")
12 |
60 |
61 |
Create a #lowercase(category.name)
62 |
63 |
64 |
65 | Are you sure?
66 |
67 |
Deleting a #lowercase(category.name) is permanent
68 |
69 |
70 |
73 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
134 | #embed("footer")
135 |
--------------------------------------------------------------------------------
/Frontend/Settings/settings.leaf:
--------------------------------------------------------------------------------
1 | #embed("header")
2 | #embed("nav")
3 | #embed("modal")
4 |
6 |
7 |
8 | #embed("errors")
9 |
10 |
65 |
66 |
67 |
68 |
69 |
70 |
118 |
119 |
120 | #embed("footer")
121 |
--------------------------------------------------------------------------------
/Frontend/Types/create-type.leaf:
--------------------------------------------------------------------------------
1 | #embed("header")
2 | #embed("nav")
3 |
10 |
11 | #embed("Types/type-fields")
12 |
13 |
14 |
15 |
16 |
81 | #embed("footer")
82 |
--------------------------------------------------------------------------------
/Frontend/Types/edit-type.leaf:
--------------------------------------------------------------------------------
1 | #embed("header")
2 | #embed("nav")
3 |
5 |
6 | #for(type in contentTypes) {
7 |
8 |
9 | #(type.plural)
10 | |
11 |
12 |
18 | |
19 |
20 | }
21 |
22 | Create a new content type
23 |
24 | #embed("footer")
25 |
--------------------------------------------------------------------------------
/Frontend/Users/create-user.leaf:
--------------------------------------------------------------------------------
1 | #embed("header")
2 | #embed("nav")
3 |