📚You can view the published version of Loop Docs here.
This repository contains the source files for Loop's documentation.
LoopDocs focuses on documenting the latest release and the dev
branch:
- What is Loop?
The Loop iOS app is a Do-It-Yourself closed-loop algorithm.
It works together with your CGM, Pump, (and Radio-link device) to manage your insulin delivery by predicting Blood Glucose outcomes. - Overview
- Requirements
- Build Loop
- Configuration
- Usage
- Troubleshooting
- Remote monitoring and commands with Nightscout
- FAQs
The easy way:
- To suggest changes, please review Issues. Add your comment if an Issue is already open, otherwise, add a new Issue.
- If it is a simple typo or wording change, follow the instructions in this video to submit a pull request the easy way.
If it is a more substantive change and you want to install LoopDocs locally and provide pull requests, please keep reading.
- Clone this project
- Install Python 3 Review Properly Installing Python for help getting Python installed.
- Install Python Virtual Environment.
In this example, I usevenv
, but use whichever you prefer.cd loopdocs # cd into the folder where you cloned this repository # Creates a virtual environment using Python 3 in the venv folder python3 -m venv venv # Activate the virtual environment # Run the next line **each time** you start a new shell window/tab source venv/bin/activate
- Install the project's required Python packages
cd loopdocs # Make sure you are in the folder where you cloned this repository python -m pip install -r requirements.txt
Once installed, you can preview the doc locally as you edit.
To preview your work as you edit:
- Run
mkdocs serve
locally and keep it running:By default, this runs a local web server that hosts the documentation at http://127.0.0.1:8000/ .cd loopdocs # the folder where you cloned this repository mkdocs serve
- Preview docs in your Web browser.
Most changes will update automatically as you edit.
Configuration and navigation changes will require restartingmkdocs serve
.
In this section we use deploy
or publish
interchangeably.
What is GitHub Pages?
GitHub Pages is a static site hosting service provided by GitHub that allows users to publish web pages directly from their GitHub repositories. It utilizes the repository content to automatically generate and serve web pages.
It is disabled by default and can be enabled per repository.
How does it work?
Whenever
gh-pages
branch is pushed to your repository, GitHub Pages will automatically deploy it to your personal GitHub website:
https://YOUR_GITHUB_USERNAME_HERE.github.io/loopdocs
Use GitHub Pages to share a preview of loopdocs
:
You can share the preview with others by building the site from your working branch and uploading the result to the gh-pages
branch of your GitHub repository. Here is how:
- Configure GitHub Pages once (See next section)
- Jump on the branch you want to share for preview
git switch my_branch
- Deploy this branch to your personal GitHub website so that others can take a look at:
mkdocs gh-deploy
Issue:
ℹ️ If you have deployed your current branch with mkdocs gh-deploy
and then pushed main
to the repository, this will automatically deploy main
and override your previous deployment.
The reason is simple, Loopdocs also has a GitHub Action that automatically builds and deploys the documentation every time the main
branch is pushed to the repository.
The workaround is to redeploy your branch for preview with mkdocs gh-deploy
.
❗️ Remember to disable GitHub Pages in your repository settings when you are done sharing.
Open your loopdocs
repository on Github: https://github.com/YOUR_GITHUB_USERNAME_HERE/loopdocs
- Click the ⚙️
"Settings"
tab (last one on the right) - Click
Pages
located under theCode and Automation
section - In the
Source
field, selectDeploy from a Branch
- First drop-down under the
Branch
section: Selectgh-pages
- Second drop-down: Select
"/(root)"
- Click
Save
To list broken links, we use the mkdocs-htmlproofer-plugin
:
CHECK_BROKEN_LINKS=true mkdocs build
To find unused (orphaned) files in the project, we use the mkdocs-unused-files
plugin:
CHECK_UNUSED_FILES=true mkdocs build
We use Google Translate to automatically translate the website into several foreign languages.
For the translation to be as correct as possible we need to give Google Translate as much context as possible.
Google Translate's automatic translation is not perfect although it does a pretty good job.
There are still some issues, where text is translated whereas it should not, like for instance:
- key, constant, identifier, filename, folder
- user interface element like a button label, field name, menu item...
- error message that should remain in English and not be translated
- brand name, project/product name,
To improve the automatic translation quality, please follow these rules when writing or updating the documentation. This will provide Google Translate with more context and enhance translation accuracy.
Updates to Eric's suggestions (from Marion)
Really - just saying the same thing in different words.
Revise the Nav labels (in mkdocs.yml) and the headers on the pages to remove words that require the no-translate tag wherever possible.
When you have to use "proper terminology" like fork
, be sure to use a no-translate tag. When possible, substitute a word that will translate. For example, make a copy
of the code. You can use app instead of Loop in many instances.
Don't get carried away with putting no-translate tags everywhere. The app itself has translations of strings included. Forcing Dosing Strategy
to not be translated is not necessary. The google translate might not match what is in the app, but forcing the English is not helpful either.
To prevent translation without modification of the font for the word or phrase use <span translate="no">
before and </span>
after the word or phrase that should not be translated. Using span
is preferred when you do not want to modify the appearance of the word or phrase. If there are spaces before or after the word or phrase, use
instead of a space. The use of span
or code
or italics (by placing an underscore or asterisk before and after the word) prevents translation and enables tooltips to still be displayed. The use of back-ticks does not allow tooltips to be displayed.
- span: no font change, tooltips display
- italics: italic font, tooltips display
- code: highlighted display, tooltips display
- backticks: highlighted display, tooltips not seen
- bold: this does not force a no-translate and can be used in addition to the other marks
New trick for dealing with variables, where appropriate, is to use $\mathit{variable-name}\$
which displays the variable-name in italics without translation and makes it clear that it is a variable.
When it is desired that the word or phrase stand out as highlighted on the page, then use back ticks or <code> </code>
instead of span
. You might want to add the
see examples below, however, this may be less of an issue because the word or phrase is highlighted on the screen and clearly differentiated from words on either side.
If "jargon" must be used in a header, be sure to use some kind of no-translate tag or it is likely to be translated to something unexpected.
Example usage below for
:
<span translate="no">Word or Phrase</span> is in the beginning of this sentence.
This is in the middle of a sentence that includes <span translate="no">Word or Phrase</span> in it.
If the word is at the end of a line or has other punctuation, the ` ` can be skipped:
### All about <span translate="no">Word</span>
This ability to build <span translate="no">Loop</span> from either a browser or using a *Mac* is wonderful.
Be warned that if
is part of the text in a header, the automatic link doesn't acknowledge the space. The link above would be #all-aboutword
, not #all-about-word
.
If you want italic font with span
, I choose to use underscore instead of asterick to make the word show up as italic font because I think that helps with clarity (opinion only):
This ability to build _<span translate="no">Loop</span>_, from both a browser and with *Mac*, is wonderful.
These words / phrases do not need no-translate tags, however, they are typically rendered in italics (use astericks on either side):
- Xcode
- Mac
- GitHub
- TestFlight
- Apple
Look out for Loop showing up as buckle, at least in French and Spanish, in translations. That indicates span
must be used, with the
required if there is no punctuation mark. Once again, using underscore instead of asterisk in concert with span
is a preference:
_<span translate="no">Loop</span>_
The no-translate tags can be avoided if used in a phrase:
- the Loop app
Common words like Secrets
that will show up on GitHub
for Building with Browser should be enclosed in code
so tooltips will work and the word will be highlighted as important.
From Eric (his rules before Marion made comments above)
To prevent Google Translate from translating specific text
items, we can mark them accordingly:
The conditional text transformation rules are expressed in two forms, pseudo-code first followed by a visual diagram.
Here is the pseudo-code version of the rules:
-
If
text
is a key, identifier, variable name, filename, folder, UI element (like the label of a button, a menu item), or an error message- If
text
is a glossary item (with a tooltip)- Surround
text
with<code>
HTML tag, like so:<code>text</code>
- Surround
- Else (not a glossary item, ie. no tooltip)
- Surround
text
with back-ticks like so:`text`
- Surround
- If
-
Else (not an Entity)
- If
text
is a product name or project name or brand name- surround it with a single
*
or_
, like so:*text*
- surround it with a single
- Else (not a product/project/brand name)
- surround it with:
<span translate="no">text</span>
- surround it with:
👀 Now the flowchart diagram that illustrates the above pseudo-code:
- If
---
title: How to prevent Google Translate from automatically translating a text?
---
flowchart TD
A[Start] --> B{Is Text a Key, Identifier,<br/> Variable, Filename, Folder, <br/>Error Message,<br/> or UI Label?}
click A "#entity"
B --> |Yes| C{is Text <br/>a Glossary Item?}
click C "#entity"
C --> |Yes| D["<code>text</code>"]
click D "#entity"
C --> |No| E[`text`]
click E "#entity"
B --> |No| F{Is Text <br/>a Product Name,<br/>a Project Name,<br/>or a Brand Name?}
click F "#name"
F --> |Yes| G[*text*]
click G "#name"
F --> |No| H["<span translate="no">text<span>"]
click H "#generic"
If the automatic translation is still incorrect after applying these rules, read this.
Now let's break down each step.
Enclose each of the following text
types with a backtick `
:
- Key
- Identifier
- Variable
- UI Element (button label, menu item...)
- Filename
- Folder
- English-only Error Message
We denote these using the generic term entity.
Examples:
Text Type | Markdown Input | Rendered Output |
---|---|---|
Key | Regenerate GitHub Token for `GH_PAT` <code>TEAMID</code> is a glossary item |
Regenerate GitHub Token for GH_PAT TEAMID is a glossary item |
Identifier | `com.1234567890.loopkit.Loop` |
com.1234567890.loopkit.Loop |
Variable | `timeSinceLastLoop` |
timeSinceLastLoop |
Button Label | Press `Click` |
Press Click |
Menu item | Select `Dexcom G6` |
Select Dexcom G6 |
Field Name | Paste it in the `Secret` field |
Paste it in the Secret field |
Filename | `BolusViewController.swift` |
BolusViewController.swift |
Folder | `Loop/View Controllers` |
Loop/View Controllers |
Error Message | `invalid curve name` |
invalid curve name |
- If
text
already exists in a code block delimited by 3 backticks.
```
let timeSinceLastLoop
```
- If
text
is a glossary item, using backticks would prevent the glossary tooltip from appearing. Instead, enclose it with a<code>
tag, like so:<code>text</code>
.
If the text
that you do not want to translate is not an Entity, read on.
To prevent a name from being automatically translated, such as a product name, project name, or brand name, use emphasis (aka. italic) by surrounding name
with a star (*
) or an underscore (_
), like so: *name*
.
Examples:
Name | Markdown Input | Rendered Output |
---|---|---|
Project Name | The *Loop* pill |
The Loop pill |
Product Name | require a *RileyLink* compatible device [...]Visit *Nightscout* documentation [...]using *Omnipod DASH* [...]the *Tidepool Mobile* uploader [...] |
require a RileyLink compatible device [...] Visit Nighscout documentation [...] using Omnipod DASH [...] the Tidepool Mobile uploader [...] |
Brand Name | on some *Medtronic* pumps |
on some Medtronic pumps |
If the text
you do not want to translate is neither an Entity nor a Name, read on.
To prevent a text
that is neither an Entity nor a Name from being automatically translated by Google Translate, surround it with a <span>
with the translate
attribute set to no
, like so:
<span translate="no">text</span>
<span translate="no">
element, make sure to review the translated output to ensure it retains the correct context and formatting.
You can also refer to the above flowchart diagram for a visual representation of the conditional text transformation rules.
Using <span translate="no">text</span>
, backticks (`text`
) or code (<code>text</code>
) has a drawback and does not work every time.
The automatic translation splits the sentence into 2 parts, one before and one after the non translated text, and can sometimes:
- get confused by this and treat them as 2 separate sentences to be translated independently.
- remove spaces around the untranslated
text
, (remember it no longer exists from Google Translate point of view)
💡Here are some possible workarounds:
-
Rewrite the sentence slightly, such as moving the
text
to the left or right end of the sentence.❌ Incorrect Translation: "The graphic below has
Show Prediction
turned off for Timeline"
✅ Improved Translation: "Show Prediction
for Timeline is turned off in the graphic below."Moving the untranslated text
Show Prediction
to the beginning of the sentence improves the translation in this case. -
If the text and surrounding words form a whole that is not reflected in the automatic translation, wrap them in a
<span>
tag. This will prevent Google Translate from separating them (without preventing the translation).
If the sentence is too short or does not provide enough context, Google Translate may get "lost" and decide to move the untranslated text to a place that makes absolutely no sense, such as the end of the sentence.
This is not a golden rule, of course.⚠️ Do not apply this blindly and systematically, because all depends on the context, so first look at the translation to apply it only where needed.Here is an example where it proved to be useful. We are materializing the fact that the words
loop
andruns
are related.❌ Incorrect Translation:
it is tied to *Loop* runs and *Nightscout* upload events
✅ Improved Translation:it is tied to <span>*Loop* runs</span>
and Nightscout upload events` -
Break a complex sentence into several simpler sentences.
You can use this if the previous approaches did not work. -
Add an unbreakable space (
) before and/or after thetext
to compensate for the missing spaces around thetext
that Google Translate removes from the translation. If the untranslatedtext
is preceded and/or followed by other words, those spaces will be removed them from the translation. Remember, untranslated text is treated as non-existent!❌ Incorrect Translation:
*<span translate="no">Loop 3</span>* or newer
✅ Improved Translation*<span translate="no">Loop 3</span>* or newer
-
Replace possessive apostrophe (
's
) with the equivalent HTML entity ('s
).
For example, to prevent the automatic translation ofTidepool
followed by a possessive apostrophe, as in this sentence, whereTidepool
is not translated, but the rest of the text, including the possessive apostrophe, is.❌ Incorrect Translation:
To use Tidepool's services
✅ Improved TranslationTo use Tidepool's services
Finding the best approach, the one that works, requires trial and error.
These rules to improve automatic translation with Google Translate comes with pluses and minuses:
- Drawbacks:
- Markdown is a bit less readable and more sprinkled with HTML.
- Need to deploy the branch to a to a public website visible to Google Translate
- Pluses:
- One single source and many potential translations
Links should be written like this:
In the same directory: Click here for [Update FAQs](update-faqs.md)
In a directory below the current page: Click here for [Update FAQs](faqs/update-faqs.md)
In a directory "outside" the current directory: Click here for [Update FAQs](../faqs/update-faqs.md)
Like above, but linking directly to a heading/anchor in update-faqs.md:
Click here for [When Should You Update?](../faqs/update-faqs.md#when-should-you-update)
❗️Make external links open in a new window by appending the {: target="_blank" }
suffix to the markdown link, like this
[LoopTips](https://loopkit.github.io/looptips){: target="_blank" }
ℹ️ Note:
- There is no space in between the link and
{: target="_blank" }
. - An external link means a link to another website (i.e. not LoopDocs).
ℹ️ Notice about mkdocs
Using absolute paths with links is not officially supported.
Relative paths are adjusted by MkDocs to ensure they are always relative to the page. Absolute paths are not modified at all.
This means that your links using absolute paths might work fine in your local environment but they might break once you deploy them to your production server.
⛔️ Do NOT use a link that starts with a '/': Click here for [Update FAQs](/faqs/update-faqs.md)
The conventions for linking to images are the same as linking to pages as described above.
New images should be placed in the img
directory just below the Markdown file.
An example of a correct link to an image is [alt-text](relative_path_to/image_name)
.
![iPhone](img/phones.png)
With images, it is possible to add extra attributes like width
and center
.
![iPhone](img/phones.png){width="300"}
ℹ️ Note that there is no space between the closing parenthesis ()
) of the link and the opening curly brace ({
). This way, the width is applied to the element to which it is attached.
This will get rendered to this:
<img alt="iPhone" src="img/phones.png" width="300">
You can also center an image, by adding {align="center"}
on a new line
just below the paragraph you want to center:
![Eros](img/eros.png){width="750"}
{align="center"}
ℹ️ Note that there is no empty/blank line between the image and {align="center"}
.
This will get rendered to this:
<p align="center">
<img alt="Eros" src="../img/eros.png" width="750" />
</p>
Use HTML on the first line that indicates the table.
For example, in displays-v3.md there are many icons with descriptions to the right.
This format provides appropriate views on both desktop and mobile.
For no header row, replace |||
with:
| <div style="width:72px"></div> | |
|--- |--- |
| ![icon alt-text](img/icon) | image description here |
To add a header row, use:
| <div style="width:72px">Column 1 Header</div> | Column 2 Header |
Admonitions, also known as call-outs, are an excellent choice for including side content without significantly interrupting the document flow.
TLDR; An admonition is a colored box with a specific icon (and a title) at the top and text content below.
Admonition is a markdown extension that enables formatted blocks for visually calling out information.
Now using the standard set of admonitions and CSS styles that come with the Material theme.
The following are the admonition types we use:
info
(blue info icon)note
(blue pencil icon)abstract
(blue notepad icon)tip
(green flame)success
(a green check mark)question
(green question mark)warning
(warning triangle)danger
(red zag icon)bug
(red bug icon)example
(a violet vial icon)quote
(a gray end quote icon)important
(red exclamation sign)
👁️ To see what each type of admonition looks like when rendered, take a look at this page.
The syntax of an admonition is:
!!! admonition_type "Title here"
Content here...
Every 4-space indented line is included in the "box" created by this admonition
where:
!!!
is a marker that denotes the start of the admonition.
It is followed by a space, then the admonition type (see above)admonition_type
is a placeholder that should be replaced with one of the types listed above.Title here
represents the title rendered in bold in the header- All subsequent lines indented with 4 spaces are considered part of the admonition's body
Example:
!!! info "New Loop Builders"
This page contains build error help for people updating their Loop app as well as brand-new Loop app builders.
!!! admonition_type_here "Title String"
If an explicit title string is provided, that is used as the title.
The displayed title string matches the capitalization provided.
Every indented line is included in the "box" created by this admonition
To remove the title, either remove the title completely or use an empty string within the double quotation marks, like so:
!!! admonition_type ""
If a blank or empty title is provided, no title is applied.
The copy-to-clipboard button is built into the Material theme for every code block and displayed on the right side.
When clicked it copies the content of the block into the clipboard.
However, we chose to disable it by default for all code blocks and enable it on a case-by-case basis.
Here is how to enable the copy-to-clipboard button for a "code" block containing regular text.
``` { .txt .copy title="title of this code block" }
Content of the code block here
```
where:
.txt
denotes the language used in the content of the code block.
For instance, use.txt
for regular text,.sh
for a regular shell script, or.bash
for a Bash script.
This is a required parameter.
Here is the list of supported languages (use one of theShort Name
s)..copy
shows the copy-to-clipboard button when present (hidden otherwise)title=“title of this code block”
adds a title to the code (none when absent)
Do note that:
- There is a space before and after the opening curly brace
{
. - There is space before the closing curly brace
}
.
LoopDocs' Glossary is like a dictionary for the acronyms and technical terms used in the documentation. It explains them in simple terms. It is kind of a personal translator for all the diabetes jargon you will find there.
The glossary is composed of a source file (text) and a generated Markdown file. The website uses the Markdown version of the glossary.
Today creating the glossary in Markdown is a 2-step manual process.
First we modify the source file (includes/tooltip-list.txt
) to add/update/remove entries.
Then we generate the Markdown version of the glossary (docs/faqs/glossary.md
).
---
title: Generate the Glossary
---
flowchart LR
subgraph Text
text_glossary[/ includes/tooltip.txt /]
end
subgraph Transform Glossary
generator{ ./make-glossary.sh }
end
subgraph Markdown
markdown_glossary[/+ docs/faqs/glossary.md /]
end
text_glossary --> generator --> markdown_glossary
- Edit the text version of the glossary
includes/tooltip-list.txt
to add/update/remove glossary entries - Create the Markdown version of the glossary (
docs/faqs/glossary.md
).
This handy script does this for you:# Transform Glossary from text to Markdown ./make-glossary.sh
- Commit both the text and markdown versions of the glossary:
git add includes/tooltip.txt docs/faqs/glossary.md git commit -m "Update Glossary: ..."