Skip to content

Urigo/tortilla

Repository files navigation

Tortilla

CircleCI

tortilla

Tortilla is a framework for building tutorials based on git and NodeJS which will help you create AWESOME tutorials and upload them to any git-host which supports markdown rendering, like GitHub.

Tortilla operates by simply wrapping an existing git project, thus providing you with some advanced git functions dedicated to create the most perfect and most beautiful tutorial in the world. In addition, Tortilla is easily accessible through a CLI, making it very convenient to use.

What's the advantages of using Tortilla over writing a simple blog-post?

  • The code and the instructions will always stay correlatively updated.
  • You can reference code snippets directly from the instructions.
  • You can use template-helpers to write complex instructions with minimal efforts.
  • You can take advantages of most git features like creating commits, tags and branches.
  • You can use neat features natively provided with the git host like reporting issues and opening pull requests.
  • The tutorial is linked directly to your git host account.
  • You can enjoy the great traffic of the git host.
  • You can easily navigate through the project at any specific point of the tutorial.
  • You can historicize different versions of your tutorial.
  • You can compare different versions of the tutorial and see the differences.
  • You can render the tutorial anywhere you want - Github, your own website, Medium and more... all at the same time
  • The list goes on and on and on...

Tutorials for example:

If you're not familiar with Tortilla I recommend you to go through the this README.md file since it contains everything you have to know about Tortilla in order to use it.

intro

Tutorial Structure

See:

Steps

Each commit should represent a single step in the tutorial, using the following message template:

Step (step index): (step description)

Here's a list of commits for example:

Step 2: Add todo-list
Step 2.3: Add todo-list controller
Step 2.2: Add todo-list view
Step 2.1: Add todo-list model
Step 1: Bundling
Step 1.3: Install the necessary packages for Webpack's build
Step 1.2: Add Webpack build to gulp tasks
Step 1.1: Create a basic Webpack config
How to create a todo list

As you can see, some of the commits represent a sub-step (e.g. step 1.1, 1.2) and some of them represent a super-step (e.g. step 1, 2); Together they form a whole single step. Note that the only exception is the root commit whose message can be whatever you'd like (will most likely be something which describes the tutorial), but the rest of the commits must follow these rules, otherwise you will encounter some unexpected behaviors.

Credit goes to @stubailo who originally came up with the commit templates concept.

Related CLI: tortilla-step CLI

Sub Step

A sub-step is a small portion of the whole step. Each sub-step should usually represent a small change which should be followed by an explanation in the tutorial. Sub-steps should be sorted by their chronological order; Sub-steps which assemble the same step should have the same super index, and a consecutive sub index separated by a period (e.g. 1.1, 1.2).

Super Step

A super-step should always come at the end of each step, and should be represented with a single index (e.g. 1, 2). The super-step should add a manual file which goes through the implementation of the associated step.

Manuals

Manuals are markdown files which should contain some handy instructions regards the implementation of each step in the tutorial. The manuals are located under the .tortilla/manuals directory, and are separated into 2 directories - templates and views. When writing manuals, we should never touch the views files, because they should be auto-generated by Tortilla's CLI. The templates directory, as the name suggests, should contain manual templates. Just so you can get the idea, here's an example of a .tortilla/manuals directory structure:

.tortilla/manuals
├─ templates
│  ├ root.tmpl
│  ├ step1.tmpl
│  ├ step2.tmpl
│  └ step3.tmpl
└─ views
   ├ root.md
   ├ step1.md
   ├ step2.md
   └ step3.md

The main difference between a manual template and a manual view is that templates are more simplified and will be most likely used for development purposes. They contain some handy template helpers we can be used to render complex markdown components, so our tutorial can be good-looking and easy-to-read, with minimum maintenance. As you can see in the files tree above, manual template files have an extension of .tmpl, unlike their belonging views which finish with an extension of .md. That's because the manual templates are not exactly markdown files, since they are packed with some extra syntactic abilities provided by Handlebars' simple yet powerful templating engine. Indeed, you can still use markdown's templating syntax, but just know that this is not a pure markdown we're talking about. The only template-view fs correlation exception is the root.tmpl file which should be mapped to the README.md file, so we can see a nice introduction for our tutorial when entering the repository. The root.md file is just a symbolic link to the main README.md file.

Note that manual templates shouldn't be written with a title, since it should be attached automatically when rendering the template's view using its belonging commit message. In addition, a navigation bar between steps should be appended at the end of the manual. For example, a root manual template which looks likes this:

- FOO
- BAR
- BAZ

And is matched with the commit message:

Les Trois Mousquetaires

Should result with the following view after rendering:

# Les Trois Mousquetaires

- FOO
- BAR
- BAZ

[{]: <helper> (navStep)

| [Begin Tutorial >](manuals/views/step1.md) |
|----------------------:|

[}]: #

Related CLI: tortilla-manual CLI

Translations

Manuals don't necessarily have to be written in English, and can be also be written in whatever language you'd choose. Translated manual templates are located under the templates/locales/your-language path, and their belonging views are localed under views/locales/your-language. Here's an example of a manuals directory with manuals which are translated into Hebrew (he):

.tortilla/manuals
├─ templates
│  ├ root.tmpl
│  ├ step1.tmpl
│  ├ step2.tmpl
│  ├ step3.tmpl
│  └ locales/he
│    ├ root.tmpl
│    ├ step1.tmpl
│    ├ step2.tmpl
│    └ step3.tmpl
└─ views
   ├ root.md
   ├ step1.md
   ├ step2.md
   ├ step3.md
   └ locales/he
     ├ root.md
     ├ step1.md
     ├ step2.md
     └ step3.md

Translations for step messages (and potentially other stuff) can be defined under the .tortilla/locales directory in a json file with the relevant language code (e.g. .tortilla/locales/he.json). Here's an example of a translation file which translates step messages:

{
  "step": {
    "root": "כיצד ליצור רשימת מטלות",
    "1.1": "יצירת קובץ הגדרות בסיסי ל Webpack",
    "1.2": "הוספת משימה של בנייה בעזרת Webpack לרשימת המשימות של gulp",
    "1.3": "התקנת החבילות הנחוצות בכדי שנוכל לבנות בעזרת Webpack",
    "1": "צרירת הפרוייקט",
    "2.1": "יצירת מודל למטלה יחידה",
    "2.2": "יצירת רשימת מטלות ויזואלית",
    "2.3": "יצירת רשימת מטלות לוגית",
    "2": "הוספת רשימת מטלות"
  }
}

Template Helpers

Template helpers are used when writing a manual file to make our lives a bit easier when it comes to formatting complex markdown components. The templates are rendered using Handlebars' templating, so I recommend you to go through its rules and syntax so you can be familiar with it, but just for the heck of demonstration, a manual template file which looks like this:

*Here's how we should use template-helpers*

{{{diffStep 1.1}}}

Should be rendered to:

*Here's how we should use template-helpers*

[{]: <helper> (diffStep 1.1)

#### Step 1.1: Demo commit

##### Added demo-file.js
\`\`\`diff
@@ -0,0 +1,3 @@
+┊ ┊1┊foo
+┊ ┊2┊bar
+┊ ┊3┊baz🚫↵
\`\`\`

[}]: #

🌟 Available {{view models}} 🌟

  • step - The number of the current step.

  • commit_message - The current commit message.

🌟 Available {{{template helpers}}} 🌟

  • navStep - A navigation bar between step manuals. Will present two buttons - "Previous step" and "Next step". This template helper may receives the following options:

    • prevRef - The reference which we will be redirected to once pressed on "Previous step" button.
    • nextRef - The reference which we will be redirected to once pressed on "Next step" button.
  • diffStep <step> - Will run git diff for the specified step's commit. This template helper may receives the following options:

    • files - A list of specific file paths separated by a comma (,) that we would like to present in our diff. The rest of the files in the diff will be ignored.
    • module - The name of the submodule which contains the step we would like to reference.
    • noTitle - A flag which indicates whether we should render the step title prior to diffs or not.

Chapter Keywords

Each chapter can be specify keywords that can help with SEO. By editing the package.json and adding a keywords section at the manual's step we can achieve. First run tortilla step edit [step] and then a your keywords. [tortilla.academy] will take care of putting these keywords together under a single meta tag based on the generated dump file.

Releases

A Tortilla project may contain release tags which represent different versions of the tutorial in different time points. Here's a list of tags for example:

In addition, a stack of all the releases is available through history branches:

master-history
foo-history

Related CLI: tortilla-release CLI

Release Tags

A release tag should represent the tutorial at a specific state (e.g. step 2 of master branch) and time point (e.g. version 1.2.1). A release tag should contain the name of the branch, the step descriptor, if at all, and a semver version, separated with at (@) signs (e.g. master@[email protected], [email protected]).

History Branches

The history is specific for a certain branch. Its name should end with history preceded by the branch name (e.g. master-history). Each commit in that branch represents all the changes made in a specific release, making the comparison between releases much easier (even if they have different roots!). Here's an example of a commits list in a history branch named master-history:

[email protected]: Add favorites page
[email protected]: Update step 2
[email protected]: Initial tutorial creation

Submodules

Often times, we would like to have a single repository where we include all the manual files, and the implementation logic would be implemented in different repositories which will be referenced from the main repository using git's submodules architecture; E.g. a single repository that includes submodules referencing the client and the server. Another advantage for that architecture is that we can implement similar applications using different stacks, or having a single back-end for multiple front-end applications, with almost identical instructions.

Related CLI: tortilla-submodule CLI

Submodules Setup

When rendering manuals which reference steps from submodules, the git host URL is taken from package.json to compose the path of the commit that contains the file. Thus, you need to define the url in package.json of the submodule repository like so:

{
  "repository": {
    "type": "git",
    "url": "https://github.com/Urigo/tortilla.git"
  }
}

Quick Startup

First you will need to install Tortilla's CLI tool:

$ sudo npm install tortilla -g

Once you have it installed you can go ahead and create a new Tortilla project:

$ tortilla create my-tutorial -m "How to create my app"

This command will initialize a new Tortilla project called my-tutorial with an initial commit message of How to create my app.

To clone the project, use the following command:

$ tortilla clone [email protected]:John/my-tutorial.git

You shouldn't be using git as Tortilla exposes all the necessary commands for it to work and contains additional logic and restrictions that will ensure that it operates as expected.

A manual page for the usage of Tortilla's CLI tool can be brought any time by typing the following:

$ tortilla --help

For further information, I'd recommend you going through the CLI section.

CLI

See:

tortilla CLI

command: tortilla create [name]

Creates a new Tortilla project with the provided name.

  • option: -o, --output [path] - The output path of the newly created project.
  • option: -m, --message [message] - The created project's initial commit's message.
  • option: --override - Override project directory if already exists.

command: tortilla init [name]

Initializes Tortilla essentials in the provided project.

command: tortilla dispose [cwd]

Removes tortilla from specified project. If no cwd is provided, the current directory will be used by default.

command: tortilla push <remote> <branch>

Push a tutorial based on the provided branch. e.g. given master then master-history, master-root, [email protected], etc, will be pushed. Note that everything will be pushed by FORCE and will override existing refs within the remote, even deleted refs.

command: tortilla pull <remote> <branch>

Pull a tutorial based on the provided branch. e.g. given master then master-history, master-root, [email protected], etc, will be pulled.

command: tortilla review <remote> <branch>

Push the necessary refs to GitHub (or any other host) and open the browser with the comparison URI. A comparison URI is one that can be used to view the diff between our changes, and the current branch in the remote. Example URI: https://github.com/Urigo/WhatsApp-Clone-Client-React/compare/7131782c5db1be873d3c315e4f60a322aa641490..c306dbe91df195d49ae52a7630c2a2fe1a215879. This will be useful to view the changes before we're actually gonna push them.

  • option: -p, --print - Don't open in the browser, only print.

command: tortilla status

Will print the tutorial status prior to git-status. If for example, we're editing step 1.2, this will print Editing step 1.2. In case there's a conflict, let's say between steps 1.2 and 1.3, this will print Solving conflict between step 1.2 (HEAD) and step 1.3.

  • option: -i, --instruct - Print additional instructions: how to continue from current state. Am I allowed to push new steps? Should I amend my changes? etc.

tortilla-dump CLI

command: tortilla dump create [out]

Dumps tutorial data as a JSON file. The default dump file name would be tutorial.json, although an optional output path might be provided. Here's a brief description of the schema of the generated dump file:

[
  {
    "branchName": "Current branch",
    "historyBranchName": "History branch matching current branch",
    "releases": [
      {
        "ReleaseVersion": "x.x.x",
        "tagName": "The name of the tag",
        "tagRevision": "The revision of the tag",
        "historyRevision": "Commit hash based on history branch",
        "changesDiff": "Diff with most recent release",
        "manuals": [
          {
            "manualTitle": "Step commit message",
            "stepRevision": "Step commit revision",
            "manualView": "Manual view content"
          }
        ]
      }
    ]
  }
]
  • option: --filter [filter] - A list of branches we would like to filter separated with spaces.
  • option: --reject [reject] - A list of branches we would like to reject separated with spaces.
  • option: --override - Override file if already exists.

command: tortilla dump diff-releases <dumpFile> <srcRelease> <dstRelease>

Creates a diff between two specified releases in a given dump file. Useful when we would like to create the diff independently from the git-project.

tortilla-manual CLI

For more information see the manuals section.

command: tortilla manual render [step]

Renders specified manual view.

  • option: --root - Render root manual (README.md).
  • option: --all - Render all manuals.

tortilla-release CLI

For more information see the releases section.

command: tortilla release bump <type>

Bumps the current release of the tutorial. This will create some new release tags accordingly and will update the associated history branch. The provided type represents a semver version type (major, minor and patch) we would like to bump. We can also specify next as the release number which will then store a weak reference to the potential upcoming version; this means that by the time we release another next version or another stable release, the most recent next version should be overridden.

  • option: -m, --message [message] - A message describing the newly created release. If not provided, and editor will be opened instead where we can type a full document.

Example: tortilla release bump next -m "Fixes from the community and dependency update"

command: tortilla release bump <type>

Reverts release to the most recent one. For example, if we have 2 releases: [email protected] and [email protected], this command will delete [email protected], leaving [email protected]. If no more releases are left, the history branch will be deleted. This is useful if we've released something by accident and we would like to fix it.

command: tortilla release list [branch]

Prints a list of all releases of the given branch. If no branch was provided, the active branch will be used by default.

command: tortilla release current

Prints the current release.

command: tortilla release diff <sourceRelease> <destinationRelease>

Runs git diff between 2 specified releases. This will also be able to run the operation between 2 different releases which are completely different from their root! You can also provide this command with some additional native git-diff options.

tortilla-step CLI

For more information see the steps section.

command: tortilla step push

Pushes a new step. Staged files will be committed along with this step.

  • option: -m, --message [message] - A message describing the newly created step.

command: tortilla step pop

Pops the most recent step. This will completely discard the step's changes.

command: tortilla step tag

Mark this step as finished and move on to the next one. This will increase the index of the super-step and zero the index of the sub-step.

  • option: -m, --message [message] - A message describing the newly created step.

command: tortilla step edit [...steps]

Edits the specified steps. A step can be specified either by index or by git-ref. This will enter rebase mode where the step's hash is at. Once finished editing, you may proceed using git-rebase commands. Alternatively, you can specify a range of steps e.g. ..1.5, 1.1.. or 1.1..1.5.

  • option: --root - Edit the root step (initial commit).
  • option: --udiff [path] - Updates the diffStep template helpers of manuals being rebased. Note that manuals prior to the current step being edited won't be updated, since the rebasing process never looks backwards. An optional can be provided which will be a reference to another repository which contains the current repository as a submodule; This will result in updating the provided repository's manuals rather than the current one. Note that submodule's package names located in package.json should be distinct.

command: tortilla step back [targetStep]

Like git rebase --continue, only it will go back instead of moving forward. Checkpoints will be based on the steps we've originally provided to the command tortilla step edit, e.g. tortilla step edit 1.1 1.2 1.3 will have steps 1.1, 1.2 and 1.3 as checkpoints. If no step was provided, we will go back to the most recent step by default. targetStep either represents one of the provided steps we would like to go back to, or it can represent a multiplier e.g. x3 that will go x times backwards in history.

  • option: -i, --interactive - Interactively pick a step from a menu.

command: tortilla step reword [step]

Rename the specified step's commit message.

  • option: -m, --message [message] - The new message of the reworded step. If not provided, and editor will be opened instead where we can type a full document.

command: tortilla step show <step>

Run git-show for given step index.

tortilla-strict CLI

Strict mode determines whether Tortilla's git-hook validations are enabled or disabled. It's highly recommended to leave it on, since you might accidentally digress from Tortilla's strict project rules.

command: tortilla strict get

Prints whether strict mode is enabled or disabled.

command: tortilla strict set <mode>

Sets strict mode. Provided mode must be either a truthy value (e.g. 1, true) or a falsy value (0, false).

tortilla-submodule CLI

Submodules are useful whenever you would like to split the tutorial into different logical segments, e.g. we will have the repo with all the instructions manual referencing the backend repo and the frontend repo.

command: tortilla submodule add <name> <url>

Like $ git submodule add, this will add the specified submodule name using the provided URL, and will detach HEAD.

command: tortilla submodule remove <name>

Will remove the submodule completely, even from the git-registry. This command doesn't exist on git and it can be very useful.

command: tortilla submodule update <name>

Will run $ git submodule update --init, and it will remove deleted files from stage if pointed object doesn't exist in submodule's remote.

command: tortilla submodule fetch <name>

Will fetch all objects from origin remote of the submodule, including tags. If the submodule is not updated, an error message will be printed instead.

command: tortilla submodule reset <name>

In other words, this will "unclone" the submodule, but will keep it initialized. This is reliable method to get away from messy situations with submodules, so whenever you don't know what to do, run this command.

command: tortilla submodule checkout <name> <ref>

This will check out the specified submodule to provided ref. It will also guide you through with some detailed instructions if you should do things beforehand, this can prevent a lot of potential issues and confusion.

example for updating submodules for WhatsApp Clone and release a new version:

# Make sure to push refs to GitHub first, on WhatsApp-Clone-Client and WhatsApp-Clone-Server
tortilla step edit --root
tortilla submodule fetch client
tortilla submodule fetch server
tortilla submodule checkout client master@next
tortilla submodule checkout server master@next
git commit --amend
git rebase --continue
tortilla release bump next

Example of reinitializing Tortilla on a repo

git checkout master
git rebase --abort
tortilla dispose
tortilla init
tortilla release bump next -m "comment"

tortilla-package CLI

package.json related commands are useful when we wanna update our dependencies' versions all across the tutorial, without needing to deal with any conflicts across the process.

command: tortilla package update-deps

This will start the dependencies updating process by creating a temporary file will contain a list of all our dependencies (merged with dev and peer) where we can specify the new versions that we would like to use in our tutorial. Once this file has been saved and closed Tortilla will handle the rebasing process.

License

MIT