diff --git a/.all-contributorsrc b/.all-contributorsrc index c914150..69d6d4a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -36,7 +36,10 @@ "question", "eventOrganizing", "talk", - "video" + "video", + "review", + "example", + "research" ] }, { @@ -63,7 +66,12 @@ "avatar_url": "https://avatars.githubusercontent.com/u/6818218?v=4", "profile": "http://llrs.dev", "contributions": [ - "review" + "review", + "content", + "question", + "research", + "doc", + "example" ] }, { @@ -73,7 +81,9 @@ "profile": "http://tdhock.github.io", "contributions": [ "review", - "example" + "example", + "research", + "question" ] }, { @@ -82,7 +92,9 @@ "avatar_url": "https://avatars.githubusercontent.com/u/3341603?v=4", "profile": "https://github.com/bettinagruen", "contributions": [ - "review" + "review", + "research", + "question" ] }, { @@ -119,7 +131,10 @@ "profile": "https://github.com/MichaelChirico", "contributions": [ "review", - "question" + "question", + "content", + "doc", + "research" ] }, { @@ -178,6 +193,29 @@ "contributions": [ "review" ] + }, + { + "login": "nbenn", + "name": "nbenn", + "avatar_url": "https://avatars.githubusercontent.com/u/3158446?v=4", + "profile": "https://github.com/nbenn", + "contributions": [ + "review", + "research", + "question" + ] + }, + { + "login": "benubah", + "name": "Ben", + "avatar_url": "https://avatars.githubusercontent.com/u/11357251?v=4", + "profile": "https://github.com/benubah", + "contributions": [ + "content", + "review", + "research", + "question" + ] } ], "contributorsPerLine": 7, @@ -185,5 +223,6 @@ "projectOwner": "r-devel", "repoType": "github", "repoHost": "https://github.com", - "skipCi": true + "skipCi": true, + "commitConvention": "angular" } diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..48d5f81 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/deploy_bookdown.yml b/.github/workflows/deploy_bookdown.yml index 73aeba2..48e4a3e 100644 --- a/.github/workflows/deploy_bookdown.yml +++ b/.github/workflows/deploy_bookdown.yml @@ -11,14 +11,19 @@ jobs: name: Render-Book runs-on: macOS-latest steps: - - uses: actions/checkout@v1 - - uses: r-lib/actions/setup-r@v1 - - uses: r-lib/actions/setup-pandoc@v1 + - uses: actions/checkout@v3 + - uses: r-lib/actions/setup-r@v2 + - uses: r-lib/actions/setup-pandoc@v2 + - uses: r-lib/actions/setup-tinytex@v2 - name: Install rmarkdown run: Rscript -e 'install.packages(c("rmarkdown","bookdown"))' - - name: Render Book - run: Rscript -e 'bookdown::render_book("index.Rmd")' - - uses: actions/upload-artifact@v1 + - name: Render HTML + run: Rscript -e 'bookdown::render_book("index.Rmd", "bookdown::gitbook")' + - name: Render PDF + run: Rscript -e 'bookdown::render_book("index.Rmd", "bookdown::pdf_book")' + - name: Render ePub + run: Rscript -e 'bookdown::render_book("index.Rmd", "bookdown::epub_book")' + - uses: actions/upload-artifact@v3 with: name: docs path: docs/ diff --git a/.gitignore b/.gitignore index a8fb504..6042139 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ .DS_Store docs/ rdevguide.rds + +# temp files +*~ diff --git a/01-Introduction.Rmd b/01-Introduction.Rmd index 6588e68..df53817 100644 --- a/01-Introduction.Rmd +++ b/01-Introduction.Rmd @@ -6,7 +6,7 @@ This guide is heavily influenced by the [Python Developer Guide](https://devguid This guide is built using bookdown which makes editing it easier, provided you have a GitHub account (sign-up at [github.com](https://github.com/)). After you log-in to GitHub, click on the ‘Edit’ icon highlighted with a red ellipse in the image below. This will take you to an editable version of the the source R Markdown file that generated the page you are on: -![](https://user-images.githubusercontent.com/28556616/122679827-03314a80-d20a-11eb-9714-06ae588127f0.png) +![Screenshot of the toolbar in the HTML version of the guide, with the Edit button (pencil and paper icon) circled in red.](img/edit_icon.png) Use the [issue tracker](https://github.com/forwards/rdevguide/issues) to raise an issue about the guide’s content or to make a feature request. diff --git a/04-reviewing_bugs_in_R.Rmd b/04-reviewing_bugs_in_R.Rmd index 0900233..4c57abb 100644 --- a/04-reviewing_bugs_in_R.Rmd +++ b/04-reviewing_bugs_in_R.Rmd @@ -40,7 +40,7 @@ If you would like to see how bugs are reviewed on Bugzilla, [here](https://bugs. **Note**: -There is a `#bugreports-for-review` channel on the [R Contributors slack](https://r-contributors.slack.com/) where you can share your bug report(s) for review/feedback before submitting to Bugzilla. This can help with checking that it really is a bug, that you have included the important information and excluded redundant information. +There is a `#bug-reporting` channel on the [R Contributors slack](https://r-contributors.slack.com/) where you can share your bug report(s) for review/feedback before submitting to Bugzilla. This can help with checking that it really is a bug, that you have included the important information and excluded redundant information. ## See also diff --git a/07-documenting_R.Rmd b/07-documenting_R.Rmd index 12d5f10..4ac7a09 100644 --- a/07-documenting_R.Rmd +++ b/07-documenting_R.Rmd @@ -68,7 +68,7 @@ The language used in the documentations should follow these basic rules: 3. Short code examples can help in understanding better. Readers can often grasp a simple example more quickly than they can digest a formal description. Usually people learn faster with concrete, motivating examples that match the context of a typical use case. -4. Giving a code equivalent (or approximate equivalent) can be a useful in addition to the description provided. You should carefully weigh whether the code equivalent adds value to the document. +4. Giving a code equivalent (or approximate equivalent) can be a useful addition to the description provided. You should carefully weigh whether the code equivalent adds value to the document. 5. The tone of the documentation needs to be respectful of the reader’s background. Lay out the relevant information, show motivating use cases, and do your best to connect-the-dots. The documentation is meant for newcomers, many of whom will be using it to evaluate the R language as a whole. The experience needs to be positive and not leave the reader with worries that something bad will happen if they make a mistake. diff --git a/08-translations.Rmd b/08-translations.Rmd new file mode 100644 index 0000000..700b051 --- /dev/null +++ b/08-translations.Rmd @@ -0,0 +1,159 @@ +# Translations + +This chapter covers internationalization in R, i.e., the display of messages in languages other than English. All +output in R (such as messages emitted by `stop()`, `warning()`, or `message()`) is eligible for translation, as +are menu labels in the GUI. Depending on the version of R that you are using, some of the languages might already +be available while others may need work. R leverages the [`gettext`](https://www.gnu.org/software/gettext/) program +to handle the conversion from English to arbitrary target languages. + +Having messages available in other languages can be an important bridge for R learners not confident in English -- +rather than learning two things at once (coding in R and processing diagnostic information in English), they can +focus on coding while getting more natural errors/warnings in their native tongue. + +The [`gettext` manual](https://www.gnu.org/software/gettext/manual/index.html) is a more canonical reference for a +deep understanding of how `gettext` works. This chapter will just give a broad overview, with particular focus on +how things work for R, with the goal of making it as low-friction as possible for developers and users to contribute +new/updated translations. + +## How translations work + +Each of the default packages distributed with R (i.e., those found in `./src/library` such as `base`, `utils`, +and `stats` and which have priority base) contains a `po` directory that is the central location for cataloguing/translating each package's +messages. + +### `.pot` files + +The `.pot` file is a snapshot of the messages available in a given **domain**. A domain in R typically identifies +a source package and a source language (either R or C/C++). For example, the file `R-stats.pot` +(found in the R sources in `./src/library/stats/po`) is a catalogue of all messages produced by R code in the +`base` package, while `stats.pot` is a catalogue of all messages produced by C code in the `stats` package. + +There are two exceptions to the basic pattern described above. The first is the domain for messages produced by +the C code which is the fundamental backing of R itself (especially, but not exclusively, the C code under +./src/main). The associated `.pot` file is `R.pot` and it is found in `./src/library/base/po`. `R-base.pot` is a +normal `.pot` file because base has a normal `R` directory. + +The second is the domain for the Windows R GUI, i.e., the text in the menus and elsewhere in the R GUI program +available for running R on Windows. These messages are stored in the `RGui.pot` domain, also in the `po` +directory for `base`, and are most commonly derived from C code found in `./src/gnuwin32`. One reason to keep +this domain separate is that it is only relevant to one platform (Windows). In particular, Windows has historically +different character encodings, so that it made more sense for Windows developers to produce translations specifically for Windows, since it is non-trivial for non-Windows users to test their translations for the Windows GUI. + +#### Generating `.pot` files + +For outside contributors, there's no need to update .pot files -- translators will typically take the R `.pot` files +as given and generate `.po` files. These will be sent along to a language-specific translation maintainer, who then +compiles them to send to the R Core developer responsible for translations, who finally applies them as a patch. + +To emphasize, this section is almost always not needed for contributing translations -- it is here for +completeness and edification. + +### `.po` files + +.po files are the most important artifacts for translators. They provide the (human-readable!) mapping between +the messages as they appear in the source code and how the messages will appear to users in translated locales. + +#### Singular messages + +Most messages appear as `msgid`/`msgstr` pairs. The former gives the message as it appears in the code, while the +latter shows how it should appear in translation. For example, here is an error in German (locale: `de`) informing +the user that their input must be of class `POSIXt` + +``` +msgid "'to' must be a \"POSIXt\" object" +msgstr "'to' muss ein \"POSIXt\" Objekt sein" +``` + +See this in context in the [`R-de.po` source file](https://svn.r-project.org/R/trunk/src/library/base/po/R-de.po). + +The same message can also be found in +[`R-it.po`](https://svn.r-project.org/R/trunk/src/library/base/po/R-it.po) +giving the translation to Italian: + +``` +msgid "'to' must be a \"POSIXt\" object" +msgstr "'to' dev'essere un oggetto \"POSIXt\"" +``` + +#### Plural messages + +Some messages will have different translations depending on some input determined at run time (e.g., the `length()` of +an input object or the `nrow()` of a `data.frame`). This presents a challenge for translation, because different languages +have different rules for how to pluralize different ordinal +numbers[^See the [relevant section](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html) of the `gettext` manual]. +For example, English typically adds `s` to any quantity of items besides 1 (1 dog, 2 dog`s`, 100 dog`s`, even 0 dog`s`). +Chinese typically does not alter the word itself in similar situations (一只狗, 两只狗, 一百只狗, 零只狗); Arabic has _six_ +different ways to pluralize a quantity. + +In `.po` files, this shows up in the form of `msgid_plural` entries, followed by several ordered `msgstr` entries. Here's an example from +[`R-de.po`](https://github.com/r-devel/r-svn/blob/c715d61cb74b3fee2d035faed9b258e86e420b75/src/library/base/po/R-de.po#L2015-L2018): + +``` +msgid "Warning message:\n" +msgid_plural "Warning messages:\n" +msgstr[0] "Warnmeldung:\n" +msgstr[1] "Warnmeldungen:\n" +``` + +The two entries in English correspond to the singular and plural messages; the two entries in German correspond similarly, because +pluralization rules in German are similar to those in English. The situation in Lithuanian +([`R-lt.po`](https://github.com/r-devel/r-svn/blob/c715d61cb74b3fee2d035faed9b258e86e420b75/src/library/base/po/R-lt.po#L1999-L2003)) +is more divergent: + +``` +msgid "Warning message:\n" +msgid_plural "Warning messages:\n" +msgstr[0] "Įspėjantis pranešimas:\n" +msgstr[1] "Įspėjantys pranešimai:\n" +msgstr[2] "Įspėjančių pranešimų:\n" +``` + +This corresponds to the 3 different ways to pluralize words in Polish. + +What do `0`, `1`, and `2` correspond to, exactly? Ideally, this will be clear to native speakers of the language, but for +clarity, it is the solution to a small arithmetic problem that can be found in the language's metadata entry. Look for the +`Plural-Forms` entry in the metadata at the top of the `.po` file; +[here it is for Lithuanian](https://github.com/r-devel/r-svn/blob/c715d61cb74b3fee2d035faed9b258e86e420b75/src/library/base/po/R-lt.po#L18-L19): + +``` +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" +``` + +`nplurals` tells us how many entries correspond to each `msgid_plural` for this language. `plural` tells us, for the +quantity `n`, which entry to use. The arithmetic is C code; most important if you really want to parse this and are only +familiar with R code is C's [ternary operator](https://en.wikipedia.org/wiki/%3F:): `test ? valueIfTrue : valueIfFalse` +is a handy way to write R's `if (test) valueIfTrue else valueIfFalse`. + +Parsing, we get the following associations: + + - the `0` entry corresponds to when a number equals 1 modulo 10 (i.e., 1, 11, 21, 31, ...) _except_ numbers equaling + 11 modulo 100 (i.e., 11, 111, 211, 311, ...). Combining, that's 1, 21, 31, ..., 91, 101, 121, 131, ..., 191, ... + - the `1` entry corresponds to numbers at least 2 modulo 10 (2, 3, ..., 8, 9, 12, 13, 14, ...) and _either_ + below 10 modulo 100 (0, 1, ..., 9, 100, 101, ..., 109, ...) _or_ exceeding 20 modulo 100 (21, 22, ..., 99). Combining, + that's 2, 3, ..., 9, 22, 23, ..., 29, 32, 33, ... 39, ..., 102, 103, ..., 109, 122, 123, ... + - The `2` entry corresponds to all other numbers, i.e. 0, 10, 11, 12, ..., 19, 20, 30, ..., 90, 100, 110, 111, 112, ... + + + + + +### `.mo` files + +`.po` files are plain text, but while helpful for human readers, this is inefficient for consumption by computers. +The .mo format is a "compiled" version of the .po file optimized for retrieving messages when R is running. + +In R-devel, the conversion from .po to .mo is done by R Core -- you don't need to compile these files yourself. +They are stored in the R sources at `./src/library/translations/inst` in various language-specific subdirectories. + +## How to contribute new translations + + + +## Current status of translations in R + +https://contributor.r-project.org/translations/ + +## Helpful references + + - Statistical terms glossary diff --git a/08-testing_pre_release_R_versions.Rmd b/09-testing_pre_release_R_versions.Rmd similarity index 100% rename from 08-testing_pre_release_R_versions.Rmd rename to 09-testing_pre_release_R_versions.Rmd diff --git a/09-R_Core_Developers.Rmd b/10-R_Core_Developers.Rmd similarity index 100% rename from 09-R_Core_Developers.Rmd rename to 10-R_Core_Developers.Rmd diff --git a/10-where_to_get_help.Rmd b/11-where_to_get_help.Rmd similarity index 100% rename from 10-where_to_get_help.Rmd rename to 11-where_to_get_help.Rmd diff --git a/11-news_and_announcements.Rmd b/12-news_and_announcements.Rmd similarity index 100% rename from 11-news_and_announcements.Rmd rename to 12-news_and_announcements.Rmd diff --git a/12-developer_tools.Rmd b/13-developer_tools.Rmd similarity index 100% rename from 12-developer_tools.Rmd rename to 13-developer_tools.Rmd diff --git a/README.md b/README.md index c6904fd..6bc391c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) -# A Guide to Contributing to R Core +# A Guide for Contributing to R Core -[![All Contributors](https://img.shields.io/badge/all_contributors-17-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-19-orange.svg?style=flat-square)](#contributors-) This guide is a work in progress, inspired by http://devguide.python.org/. It is currently deployed at https://forwards.github.io/rdevguide/. @@ -23,6 +23,11 @@ You can also suggest changes by editing the .Rmd files that are at the root of t You can push directly to `master` for small fixes. Please use PRs to `master` for discussing larger updates - try to limit to one section or at least one chapter in each PR, so that changes are easier to review. +## Editing notes + +* Images must be included in the source, not provided as URLs, for the PDF book to compile. +* Images should have alt text for accessibility - note this is shown as a caption in the EPUB version. + ## Technical details Deployment is done via Travis CI: @@ -33,7 +38,7 @@ If you want to render the guide locally, you need to install `bookdown`. Then us ```bookdown::render_book('index.Rmd', 'bookdown::gitbook')``` -and the book will be generated in the `docs` folder. You can open the guide on the command line via `open docs/index.html`. +and the book will be generated in the `docs` folder. You can open the guide on the command line via `open docs/index.html`. To preview the PDF or EPUB versions locally, replace `'bookdown::gitbook'` with `'bookdown::pdf_book'` or `'bookdown::epub_book`' as appropriate. ## Code of Conduct @@ -54,29 +59,33 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

Heather Turner

🖋 💻 🚧 🧑‍🏫 📆 👀 🔍 💬 📋 📢

Saranjeet Kaur

🖋 📖 🤔 🔍 💬 📋 📢 📹

Maya Gans

🚇

Carol Willing

👀

Lluís

👀

Toby Dylan Hocking

👀 💡

bettinagruen

👀

Martin Mächler

👀

Anelda van der Walt

👀

Mine Cetinkaya-Rundel

👀

Michael Chirico

👀 💬

Elin Waring

💬

Michael Lawrence

👀 🤔 🧑‍🏫

Gabe Becker

👀 💬

Kirill Müller

💬

Lionel Henry

💬

John Hayes

👀
Heather Turner
Heather Turner

🖋 💻 🚧 🧑‍🏫 📆 👀 🔍 💬 📋 📢
Saranjeet Kaur
Saranjeet Kaur

🖋 📖 🤔 🔍 💬 📋 📢 📹 👀 💡 🔬
Maya Gans
Maya Gans

🚇
Carol Willing
Carol Willing

👀
Lluís
Lluís

👀 🖋 💬 🔬 📖 💡
Toby Dylan Hocking
Toby Dylan Hocking

👀 💡 🔬 💬
bettinagruen
bettinagruen

👀 🔬 💬
Martin Mächler
Martin Mächler

👀
Anelda van der Walt
Anelda van der Walt

👀
Mine Cetinkaya-Rundel
Mine Cetinkaya-Rundel

👀
Michael Chirico
Michael Chirico

👀 💬 🖋 📖 🔬
Elin Waring
Elin Waring

💬
Michael Lawrence
Michael Lawrence

👀 🤔 🧑‍🏫
Gabe Becker
Gabe Becker

👀 💬
Kirill Müller
Kirill Müller

💬
Lionel Henry
Lionel Henry

💬
John Hayes
John Hayes

👀
nbenn
nbenn

👀 🔬 💬
Ben
Ben

🖋 👀 🔬 💬
diff --git a/_output.yml b/_output.yml index 11d8e3f..7eeeb1b 100644 --- a/_output.yml +++ b/_output.yml @@ -13,3 +13,11 @@ bookdown::gitbook: after: |
  • Published with bookdown
  • + download: ["pdf", "epub"] +bookdown::pdf_book: + includes: + in_header: preamble.tex + latex_engine: xelatex + citation_package: natbib + keep_tex: yes +bookdown::epub_book: default diff --git a/header.html b/header.html index 10e4a48..73b0fd7 100644 --- a/header.html +++ b/header.html @@ -1,3 +1,4 @@ + diff --git a/img/ccby.png b/img/ccby.png new file mode 100644 index 0000000..cf59608 Binary files /dev/null and b/img/ccby.png differ diff --git a/img/edit_icon.png b/img/edit_icon.png new file mode 100644 index 0000000..b1f07da Binary files /dev/null and b/img/edit_icon.png differ diff --git a/img/favicon.png b/img/favicon.png new file mode 100644 index 0000000..79ca953 Binary files /dev/null and b/img/favicon.png differ diff --git a/index.Rmd b/index.Rmd index d5c0cb2..f1be43a 100644 --- a/index.Rmd +++ b/index.Rmd @@ -3,19 +3,27 @@ title: "R Development Guide" author: "R Contribution Working Group" date: "`r Sys.Date()`" site: bookdown::bookdown_site +output: bookdown::gitbook documentclass: book bibliography: [book.bib] biblio-style: apalike link-citations: yes github-repo: forwards/rdevguide url: 'TDDO' +cover-image: "img/Rlogo.png" +favicon: "img/Rlogo.svg" description: "A guide to R development." --- -# {-} -Initial chapters of this guide were developed by Saranjeet Kaur Bhogal, in a project funded by the R Foundation, mentored by Heather Turner and Michael Lawrence. It draws on documentation and articles written by the R Core Team. +# Acknowledgement -This guide has benefited from contributions and reviews by the following (names are in alphabetical order): +This guide draws on documentation and articles written by the R Core Team. +Initial chapters of the guide were developed by Saranjeet Kaur Bhogal, in a project funded by the R Foundation, mentored by Heather Turner and Michael Lawrence. This initial version was upgraded in a [Google Season of Docs 2022](https://github.com/rstats-gsod/gsod2022/wiki/GSOD-2022-Proposal) project with Saranjeet Kaur Bhogal and Lluís Revilla Sancho working as technical writers managed by Nicolas Bennett and overseen by a [Steering Committee](https://github.com/rstats-gsod/gsod2022/wiki/GSOD-2022-Proposal#steering-committee) including representatives from R Core and the wider R community. -Bettina Gruen, Carol Willing, Gabriel Becker, Kara Woo, Lluís Revilla Sancho, Maya Gans, Michael Chirico, Mine Cetinkaya-Rundel, Toby Dylan Hocking. +This guide has benefited and continues to be benefit from varied contributions by several [contributors](https://github.com/r-devel/rdevguide#contributors-). + + +[![License: CC BY 4.0](img/ccby.png)](https://creativecommons.org/licenses/by/4.0/){width=180px} + +This project is licensed under a [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). Some pages may contain materials that are subject to copyright, in which case you will see the copyright notice.