Tool for Swift Playground books

Overview

CircleCI

playgroundbook

A series of tools for Swift Playground and Playground books based on Apple's documentation.

It's a work in progress (see issues) but you can use it now.

Installation

> [sudo] gem install playgroundbook

Usage

To lint an existing playground book:

> playgroundbook lint MyPlaygroundbook.playgroundbook

To generate a playground book:

> playgroundbook render book.yaml

The yml file should be in the following format:

name: Testing book
identifier: com.ashfurrow.example
resources: assets # Optional
cover: cover.jpeg # Optional
deployment_target: ios10.0 # Optional
imports: # Optional, defaults to UIKit
 - UIKit
 - CoreGraphics
chapters:
  - name: Chapter 1
    edge_to_edge_live_view: false # defaults to true
    live_view_mode: "VisibleByDefault" # defaults to "HiddenByDefault"
  - name: Chapter 2
  - etc...
glossary:
  term: definition

Note that you can't use tabs when indenting in the .yaml file. Everything needs to have spaces in order to work properly. Otherwise you will end up with parse errors.

Each chapter needs to have a corresponding playground; so Chapter 1 requires there be a Chapter 1.playground playground. Your directory should look like this:

Once you've created a playground for each chapter, it's time to add pages to your playgrounds. You can do this in Xcode.

Note that the order of the pages is determined by the ordering of the filesystem, which is lexicographical. You also can't have any periods in your pages.

Then run the render command in the directory containing the yaml file.

playgroundbook render book.yaml

The playgrounds can reference (not copy) resources from an optionally specified directory. import frameworks are specified in the yaml file and are added to every page of the book. You can specify a cover image file name that's stored in the resources directory (it should be 400x300 pixels). Finally, you can supply a glossary, a dictionary of term/definition pairs. This lets you link to terms in markdown. For example:

... [term](glossary://term) ...

Only the link to the term must be URL encoded. For example, the term "reuse identifier" would be defined in the yaml as reuse identifier but linked to as glossary://reuse%20identifier.

Each page in a chapter's .playground will be a separate page in the .playgroundbook and it's Source. The contents of the Source and Resource folders for each chapter and each page are copied.

Limitations of Book Rendering

Playground books support a rich set of awesome features to make learning how to code really easy, and this tool only scratches the surface. Read over the Playground Book reference to see all the available options. If you have suggestions, please open an issue πŸ‘

Creating a Playground from markdown

Maybe you want to do something for a website, or a git repo first, and then generate your Playground? Well in those cases your source of truth is the markdown document. For that case, we have playgroundbook wrapper.

For example, you might have a folder that looks like:

> tree Beginners/Lesson\ One

Beginners/Lesson\ One
β”œβ”€β”€ README.md
β”œβ”€β”€ README_ZH.md
└── img
    β”œβ”€β”€ emptyplayground.png
    β”œβ”€β”€ multipleresults.png
    β”œβ”€β”€ newplayground.png
    β”œβ”€β”€ results.png
    β”œβ”€β”€ tentimes.png
    └── welcome.png

You can run:

playgroundbook wrapper "Beginners/Lesson\ One/README.md" "Lesson One"

And it will switch out swift codeblocks into the playground. You have to use triple backticks with swift ```swift. No space between them. You should avoid using backtick blocks for anything other than Swift code, if you need to show examples, use Markdown's indentation rules with four spaces.

> tree Beginners/Lesson\ One

Beginners/Lesson\ One
β”œβ”€β”€ Lesson\ One.playground
β”‚   β”œβ”€β”€ Contents.swift
β”‚   β”œβ”€β”€ Resources
β”‚   β”‚   └── img
β”‚   β”‚       β”œβ”€β”€ emptyplayground.png
β”‚   β”‚       β”œβ”€β”€ newplayground.png
β”‚   β”‚       β”œβ”€β”€ results.png
β”‚   β”‚       └── welcome.png
β”‚   β”œβ”€β”€ contents.xcplayground
β”‚   └── timeline.xctimeline
β”œβ”€β”€ README.md
...

You might notice that a subset of images, have moved well, they're the only one being used in the README.md. Slick huh?

Contributing

Hey! Like this tool? Awesome! We could actually really use your help!

Open source isn't just writing code. We could use your help with any of the following:

  • Finding (and reporting!) bugs.
  • New feature suggestions.
  • Answering questions on issues.
  • Reviewing pull requests.
  • Helping to manage issue priorities.
  • Fixing bugs/new features.

If any of that sounds cool to you, send a pull request! After a few contributions, we'll add you as an admin to the repo so you can merge pull requests and help steer the ship 🚒 You can read more details about that in our contributor guidelines.

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by [its terms](Code of Conduct.md).

License

MIT, except for the starter.playgroundbook in the unit tests, which is licensed by Apple.

Comments
  • No autocomplete in Playgrounds Book

    No autocomplete in Playgrounds Book

    Hi all, Once I get the file & folder structure for a .playgroundbook, I import necessary classes and put them in the sources folder. Then, on the individual Contents.swift files for each page, I try to reference the class and initialize it, add it to the live view, etc. Not only am I unable to get any autocomplete whatsoever, it does not show any suggestions for regular UIKit and Foundation stuff, like trying to create a new variable for a view, string, etc. Even when writing in the Class file from my other project that I copied over, it compiles/shows autocomplete in the separate playground, and once put in the .playgroundbook Project, nothing.

    I'm thinking that it doesn't compile anything in Xcode, and will only actually compile once you load it onto the iPad, however, it doesn't seem practical to write all my code in a separate project so that I can get completition when writing.

    I will get a project uploaded shortly.

    opened by ryanoconnor7 21
  • Add support for playgrounds with multiple pages

    Add support for playgrounds with multiple pages

    Playgrounds for Xcode can have multiple pages. When you add a new page, the file structure becomes:

    Chapter\ 1.playground/
    β”œβ”€β”€ Pages
    β”‚Β Β  β”œβ”€β”€ My\ First\ Page.xcplaygroundpage
    β”‚Β Β  β”‚Β Β  └── Contents.swift
    β”‚Β Β  └── My\ Second\ Page.xcplaygroundpage
    β”‚Β Β      └── Contents.swift
    β”œβ”€β”€ Sources
    β”‚Β Β  └── Preamble.swift
    β”œβ”€β”€ contents.xcplayground
    └── playground.xcworkspace
        β”œβ”€β”€ contents.xcworkspacedata
        └── xcuserdata
            └── [USERNAME].xcuserdatad
                └── UserInterfaceState.xcuserstate
    

    The default Playground (with only one page) has a file structure of:

    Chapter\ 2.playground/
    β”œβ”€β”€ Contents.swift
    β”œβ”€β”€ contents.xcplayground
    └── playground.xcworkspace
        β”œβ”€β”€ contents.xcworkspacedata
        └── xcuserdata
            └── [USERNAME].xcuserdatad
                └── UserInterfaceState.xcuserstate
    

    I believe that taking advantage of this structure is better than putting everything in a single Contents.swift. This is currently just a proof of concept (not fully implemented and no tests).

    Work in Progress:

    • [x] Transfer the entire contents of Sources instead of looking for Sources/Preample.swift
    • [x] Transfer contents of Resources from .playground to .playgroundchapter
    • [x] Transfer contents of Sources from .xcplaygroundpage to .playgroundpage
    • [x] Transfer contents of Resources from .xcplaygroundpage to .playgroundpage
    • [x] Decide if old way (single file with //// split) should still be supported
    • [x] Update documentation
    • [ ] Rip out //// code
    • [ ] Update tests

    You can test it against this repo (the generated .playgroundbook is included in the repo).

    opened by dionlarson 15
  • Initial work on Rendering

    Initial work on Rendering

    Fixes #14.

    Basically I'm splitting the project into two independent code paths: one for linting and one for rendering. Feedback welcome as always.

    Left to complete:

    • [x] Generate playground chapter and page directories for each chapter.
    • [x] Generate a manifest for each chapter.
    • [x] Generate a manifest for each page.
    • [x] Copy each playground page to the approach playground chapter's page directory.
    • [x] Update documentation in readme.
    • [x] More UI output.
    opened by ashfurrow 8
  • Support for Glossary

    Support for Glossary

    Glossaries are a really cool feature, and I think this tool needs to support them. They're easy enough to use, just a plist that's a literal dictionary, but they have this "First Use" thing that gets tricky. Here's an amended example from one of Apple's books:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Terms</key>
        <dict>
            <key>while loop</key>
            <dict>
                <key>Definition</key>
                <string>A block of code that runs for as long as a given condition is true. When the condition changes to false, the loop stops running. 
    </string>
                <key>FirstUse</key>
                <dict>
                    <key>PageReference</key>
                    <string>While%20Loops/Introduction</string>
                    <key>Title</key>
                    <string>While Loops</string>
                </dict>
            </dict>
        </dict>
    </dict>
    </plist>
    

    I haven't figured out what the PageReference or Title are for yet. Help would be appreciated.

    enhancement help wanted 
    opened by ashfurrow 7
  • Copy SPM Sources into top-level Sources for book

    Copy SPM Sources into top-level Sources for book

    This could be a very barebones solution for https://github.com/playgroundbooks/playgroundbook/issues/21

    Assuming a Package.swift file specifying libraries to be used these can be copied into the .playgroundbook after being fetched by SPM.

    It seems to me that SPM is the most straightforward option for including libraries in a playground book as well as having the least caveats associated with it.

    A couple of tweaks to make this more useful could be:

    • [x] Copy into source playgrounds to support work in Xcode
    • [ ] Allow more granular destinations (chapter or page) to be specified in YAML
    opened by flufff42 5
  • Add Rubocop to project

    Add Rubocop to project

    This PR aims to clean up the existing codebase and address #7 by adding Rubocop to the project. I've also gone ahead and had Rubocop go through and automatically fix style violations where it can, but a few still remain that I'd like to address before merging this PR.

    opened by rhysforyou 5
  • Glossary

    Glossary

    Fixes #18.

    This is a work-in-progress because I haven't had a chance to test it with Swift Playgrounds to make sure it works. It's a bit messy, might be a better way to do this in Ruby. I'll check out to see if it works next week.

    opened by ashfurrow 4
  • Removes extraneous newlines.

    Removes extraneous newlines.

    Fixes #20.

    Regexes gave me trouble for stripping lines like

    //: Some markdown.
    
    
    

    I originally used squeeze("\n") but that strips consecutive newlines in code, which is not good (I added a test for that). So my solution was to split based on a regex that used \n* and then join. The problem is that this adds a newline before any matched components, so I make sure to remove newlines preceding //: comments after that check. Let me know what you think, I'm sure there's a better solution.

    opened by ashfurrow 4
  • Extract chapter name from hash

    Extract chapter name from hash

    I introduced a bug yesterday, which led to chapter names not being extracted from the hash resulting in chapter names in the Manifest.plist being "{\"name\"=>\"test_chapter\"}.playgroundchapter" instead of test_chapter.plagroundchapter.

    opened by pietbrauer 3
  • Make Page manifest customisable through YAML

    Make Page manifest customisable through YAML

    As discussed in #36 I am proposing a new layout for the chapters sections of the YAML:

    Before:

    chapters:
      - "Chapter 1"
      - "Chapter 2"
    

    After:_

    chapters:
      - name: "Chapter 1"
         EdgeToEdgeLiveView: true
      - name: "Chapter 2"
         EdgeToEdgeLiveView: false
    

    A proposed implementation can be viewed in #42

    enhancement 
    opened by pietbrauer 3
  • Release new version reflecting changes to chapter configuration

    Release new version reflecting changes to chapter configuration

    It seems that after merging changes to the chapter configuration in the YAML file used for rendering a book no new version was tagged.

    Could a new version be released to include these changes?

    opened by flufff42 2
  • Loss of granularity of per-page options

    Loss of granularity of per-page options

    It seems that in the book.yaml file I set options (such as having an edge-to-edge live view) on a chapter. But these options are actually properties of an individual page, not of a chapter. There is a loss of granularity here.

    opened by rgov 1
  • Reconsider default options

    Reconsider default options

    edge_to_edge_live_view defaults to false but I always set it to true. live_view_mode defaults to HiddenByDefault but I always end up setting it to VisibleByDefault. I think I'd like to change these to be the new defaults, since they're the common case. @playgroundbooks/contributors any thoughts?

    opened by ashfurrow 3
  • Failed to open and parse playground chapter.

    Failed to open and parse playground chapter.

    For some reason I am not able to render the book.yaml file

    Output

    Rendering book.yaml...
    Failed to open and parse playground chapter.
    /Library/Ruby/Gems/2.0.0/gems/playgroundbook-1.1.0/lib/renderer/playgroundbook_renderer.rb:68:in `block in render': Missing valid playground for Chapter 1. (RuntimeError)
    	from /Library/Ruby/Gems/2.0.0/gems/playgroundbook-1.1.0/lib/renderer/playgroundbook_renderer.rb:46:in `map'
    	from /Library/Ruby/Gems/2.0.0/gems/playgroundbook-1.1.0/lib/renderer/playgroundbook_renderer.rb:46:in `render'
    	from /Library/Ruby/Gems/2.0.0/gems/playgroundbook-1.1.0/bin/playgroundbook:17:in `<top (required)>'
    	from /usr/local/bin/playgroundbook:22:in `load'
    	from /usr/local/bin/playgroundbook:22:in `<main>'
    

    Note: I wasn't able to install playgroundbook as described in the readme. When I tried to run

    sudo gem install playgroundbook
    

    I got this error

    ERROR:  While executing gem ... (Errno::EPERM)
        Operation not permitted - /usr/bin/playgroundbook
    

    So I had to install it like this

    sudo gem install -n /usr/local/bin playgroundbook
    

    Output

    Successfully installed playgroundbook-1.1.0
    Parsing documentation for playgroundbook-1.1.0
    1 gem installed
    
    bug 
    opened by ag 5
  • Support LiveView.swift

    Support LiveView.swift

    In the sample code provided by Apple called TalkingToTheLiveView, for each page there is a LiveView.swift file that contains few lines of code

    import PlaygroundSupport
    let page = PlaygroundPage.current
    page.liveView = FaceViewController()
    

    Those files are located besides Contents.swift inside each .playgroundpage folder.

    live

    I find them very useful if the reader shouldn't be able to mess with most of the code of the Live View, but instead just interact with it through the PlaygroundSupport Module.

    I don't have specific tests but probably the LiveView.swift file won't be recompiled each time the editor is updated, to achieve optimal performances.

    opened by macteo 6
Releases(0.1.0)
Owner
Swift Playground Books
Tools for improving work with Swift Playgrounds + Playground Books
Swift Playground Books
An adorable little framework and command line tool for interacting with SourceKit.

SourceKitten An adorable little framework and command line tool for interacting with SourceKit. SourceKitten links and communicates with sourcekitd.fr

JP Simard 2.1k Jan 5, 2023
Xcode-compatible build tool.

xcbuild xcbuild is an Xcode-compatible build tool with the goal of providing faster builds, better documentation of the build process and running on m

Meta Archive 2k Dec 11, 2022
Swift CLI for strong-typing images, colors, storyboards, fonts and localizations

Shark Shark is a Swift command line tool that generates type safe enums for your images, colors, storyboards, fonts and localizations. Because Shark r

Kaan Dedeoglu 377 Dec 1, 2022
Strong typed, autocompleted resources like images, fonts and segues in Swift projects

R.swift Get strong typed, autocompleted resources like images, fonts and segues in Swift projects Why use this? It makes your code that uses resources

Mathijs Kadijk 8.9k Jan 6, 2023
Soulful docs for Swift & Objective-C

jazzy is a command-line utility that generates documentation for Swift or Objective-C About Both Swift and Objective-C projects are supported. Instead

Realm 7.2k Jan 3, 2023
Laurine - Localization code generator written in Swift. Sweet!

Author's note: Thanks everyone for making Laurine the TOP trending Swift repository in the world - this is amazing and very heart-warming! But this is

Jiri Trecak 1.3k Dec 28, 2022
swiftenv allows you to easily install, and switch between multiple versions of Swift.

Swift Version Manager swiftenv allows you to easily install, and switch between multiple versions of Swift. This project was heavily inspired by pyenv

Kyle Fuller 1.9k Dec 27, 2022
Script to support easily using Xcode Asset Catalog in Swift.

Misen Misen is a script to support using Xcode Asset Catalog in Swift. Features Misen scans sub-directories in the specified Asset Catalog and creates

Kazunobu Tasaka 123 Jun 29, 2022
An Xcode Plugin to convert Objective-C to Swift

XCSwiftr Convert Objective-C code into Swift from within Xcode. This plugin uses the Java applet of objc2swift to do the conversion. Noticed that the

Ignacio Romero Zurbuchen 338 Nov 29, 2022
Swift autocompleter for Sublime Text, via the adorable SourceKitten framework

SwiftKitten SwiftKitten is a Swift autocompleter for Sublime Text, via the adorable SourceKitten framework. Faster than XCode ! This package is new an

John Snyder 142 Sep 9, 2022
A command line tool for managing Swift Playground projects on your Mac.

swift-playground-tools A command line tool for managing Swift Playground projects on your Mac. Generate Xcode Project $ playground-tools generate-xcod

Liam Nichols 0 Dec 31, 2021
DevTool - A simple UI and powerful Mac OS application, Such as JSON-Formatting tool, JSON-to-model tool, AppIcon generator, Network-Request tool...

?? ?? ?? A simple UI and powerful Mac OS application. It is a collection of tools commonly used in my development work. Such as JSON-Formatting tool, JSON-to-model tool, AppIcon generator, Network-Request tool...

渠晓友 3 Dec 21, 2022
Paul Veillard 4 Mar 31, 2022
iOS Open Source Application written in Swift. App to manage borrowed books at UFRGS using SABI.

RenovaLivrosUFRGS iOS Open Source Application written in Swift. App to manage borrowed books at UFRGS using SABI. App in portuguese, code and comments

Matheus Cavalca 5 Feb 10, 2022
iOS custom view to display books on shelf

ShelfView (iOS) iOS custom view to display books on shelf (Android version is available here) Requirements iOS 10.0+ Swift 4.2 Installation ShelfView

Adeyinka Adediji 268 Dec 10, 2022
With the Coverless App, you can discover many books of various genres

Coverless NΓ£o julgue um livro pela capa: use a sinopse! Com o App Coverless, vocΓͺ pode descobrir muitos livros de vΓ‘rios gΓͺneros. Salve seus livros de

Oliver (Bruno) 1 Oct 26, 2021
A simple iOS app similar to iTunes where you can view details of your favorite movies, songs and audio books.

Popcorn Adventure This is an iOS app developed by Arthur Tristan M. Ramos who has taken the Appetiser iOS Coding Challenge. Design Pattern The design

Arthur Tristan M. Ramos 0 Dec 11, 2021
Library that holds multiple books loaded from json in a scroll view where each book can be tapped on, favorited, rated, and opened to read

Library that holds multiple books loaded from json in a scroll view where each book can be tapped on, favorited, rated, and opened to read. If a book is a favorite, an orange star appears on the book's cover. Page number, favorites, and ratings are saved for each session of the app.

Eli Hartnett 0 Dec 27, 2021
ReadMe app is here to list all of the physical books in your personal library

ReadMe App The ReadMe app is here to list all of the physical books in your personal library, mark books you still have to read review books after you

Ihor Muliar 1 Nov 23, 2021
Uses Firestore to remotely store books that are sorted by genre locally.

Uses Firestore to remotely store books that are sorted by genre locally. Books can be added, removed, or edited from within the app or on Firebase.

Eli Hartnett 0 Jul 9, 2022