mirror of
https://github.com/EbookFoundation/free-programming-books.git
synced 2025-07-31 13:10:14 +02:00
* Add RTL/LTR Markdown linter for mixed-direction text consistency and PR annotation Introduce a Python-based linter (scripts/rtl_ltr_linter.py) to automatically detect and annotate issues related to mixed Right-To-Left (RTL) and Left-To-Right (LTR) text in Markdown files. The linter analyzes list items, book entries, and metadata for potential bidirectional text rendering problems, such as missing Unicode directionality markers (RLM/LRM) and improper handling of LTR keywords or symbols in RTL contexts. Key features: - Scans all Markdown files in the repository, with full logs saved as workflow artifacts. - Annotates only changed or added lines in pull requests, providing targeted feedback in the GitHub Actions Job Summary. - Detects common RTL/LTR issues, including: - Missing directionality markers after LTR keywords (e.g., "HTML") or symbols (e.g., "C#") in RTL text. - BIDI (bidirectional) mismatches that may affect text display. - Incorrect ordering of author names and metadata in RTL contexts. - Configurable via rtl_linter_config.yml for keywords, symbols, and severity levels. - Includes a GitHub Actions workflow (rtl-ltr-linter.yml) for automated checks on PRs. * Add test cases for RTL/LTR linter in English and Arabic book lists Add sample entries to free-programming-books-en.md and free-programming-books-ar.md to test the RTL/LTR Markdown linter. These test cases include various combinations of RTL and LTR text, keywords, symbols, and metadata to verify that the linter correctly detects directionality issues and outputs the expected logs and annotations. * Restore original book lists after RTL/LTR linter test cases Revert test entries in free-programming-books-en.md and free-programming-books-ar.md, restoring the original book lists. This commit removes temporary test data used for validating the RTL/LTR Markdown linter, preparing the repository for merging the PR with a clean state. No functional changes to the linter or configuration files; only test content has been removed. * Update RTL/LTR linter workflow and script: run only on RTL file changes or "RTL" label, fail only on errors The GitHub Actions workflow for the RTL/LTR Markdown linter now runs only if: - The PR modifies .md files related to RTL languages (ar, he, fa, ur), or - The PR has the "RTL" label. The linter script has been updated to fail the check only if errors are found on changed lines, not for warnings. * Only upload linter artifact if linter step runs Prevent warning about missing artifact by uploading the linter output log only if the linter step was executed (success or failure). This avoids unnecessary warnings when the linter is skipped because no RTL files were changed and no RTL label is present. * Test workflow: modify non-RTL markdown file Modified free-programming-books-en.md to verify that the RTL/LTR linter workflow does not run when only non-RTL markdown files are changed and the "RTL" label is not present. * Test workflow: modify RTL markdown file to trigger linter Modified free-programming-books-ar.md to verify that the RTL/LTR linter workflow runs as expected when an RTL markdown file is changed. * Fix RTL/LTR BIDI issues in some markdown files Applied directional markers (‎, ‏) and other formatting fixes to resolve BIDI (bidirectional text) errors and warnings reported by the linter in several .md files. * Fix workflow: upload linter log only if linter step has not been skipped Updated the workflow to upload the linter output artifact only when the linter step was actually executed (not skipped) * Add debug step to check linter outcome in workflow Added a debug step after the linter execution in the workflow to print the outcome and conclusion of the run_linter step. * Set continue-on-error for linter step to allow artifact upload and debug * Remove workflow debug step and update markdown file Removed the debug step from the RTL/LTR linter workflow and applied further changes to a markdown file. * Fix RTL/LTR BIDI issues in some markdown files Applied directional markers (‎, ‏) and other formatting fixes to resolve BIDI (bidirectional text) errors and warnings reported by the linter in several .md files. This commit is a second batch of corrections to improve RTL/LTR rendering and pass the linter checks. * Fix RTL/LTR BIDI issues in some markdown files Applied directional markers (‎, ‏) and other formatting fixes to resolve BIDI (bidirectional text) errors and warnings reported by the linter in several .md files. This commit is a third batch of corrections to improve RTL/LTR rendering and pass the linter checks. * Do not produce log file if no issues found Updated the linter script to avoid creating the log file when no issues, warnings, or notices are found. If no issues are detected, the script now prints a "::notice ::No issues found" * Always print annotation with number of errors and warnings found Updated the linter script to always print an annotation indicating how many errors and warnings were found, even if there are none. * Fix: always print summary annotation with number of issues found * Add a missing newline character at end of file free-courses-he.md * Update linter configuration and revert markdown files to pre-fix state Updated the organization of keywords and symbols in the linter configuration file. Reverted all markdown files to their original state prior to the fixes. * Update free-programming-books-he.md with fixes * Update free-programming-books-he.md with further fixes * Update free-programming-books-he.md with fixes * Update free-programming-books-fa_IR.md with fixes * Update free-programming-books-he.md with further fixes * Update free-programming-books-ar.md with fixes * Update free-programming-books-ar.md with further fixes * Update free-podcasts-screencasts-ar.md with fixes * Update free-podcasts-screencasts-fa_IR.md with fixes * Update free-courses-he.md with fixes * Update free-courses-he.md with further fixes * Update free-courses-fa_IR.md with fixes * Update free-courses-fa_IR.md with further fixes * Update free-courses-ar.md with fixes * Update free-courses-ar.md with further fixes * Update free-courses-ar.md with further fixes * Update free-courses-ur.md with fixes * Update some markdown files with further improvements * Fix alignment of nested lists in free-programming-books-fa_IR.md * Update CONTRIBUTING.md and CONTRIBUTING-it.md with RTL/LTR linter error fixing guidelines Added a section to CONTRIBUTING.md and CONTRIBUTING-it.md explaining how to fix RTL/LTR Markdown linter errors, including when to use ‏ and ‎ with practical examples for contributors working on files with mixed RTL and LTR text
338 lines
16 KiB
Markdown
338 lines
16 KiB
Markdown
*[Read this in other languages](README.md#translations)*
|
||
|
||
|
||
## Contributor License Agreement
|
||
|
||
By contributing, you agree to the [LICENSE](../LICENSE) of this repository.
|
||
|
||
|
||
## Contributor Code of Conduct
|
||
|
||
By contributing, you agree to respect the [Code of Conduct](CODE_OF_CONDUCT.md) of this repository. ([translations](README.md#translations))
|
||
|
||
|
||
## In a nutshell
|
||
|
||
1. "A link to easily download a book" is not always a link to a *free* book. Please only contribute free content. Make sure it's free. We do not accept links to pages that *require* working email addresses to obtain books, but we welcome listings that request them.
|
||
|
||
2. You don't have to know Git: if you found something of interest which is *not already in this repo*, please open an [Issue](https://github.com/EbookFoundation/free-programming-books/issues) with your links propositions.
|
||
- If you know Git, please Fork the repo and send Pull Requests (PR).
|
||
|
||
3. We have 6 kinds of lists. Choose the right one:
|
||
|
||
- *Books* : PDF, HTML, ePub, a gitbook.io based site, a Git repo, etc.
|
||
- *Courses* : A course is a learning material which is not a book. [This is a course](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/).
|
||
- *Interactive Tutorials* : An interactive website which lets the user type code or commands and evaluates the result (by "evaluate" we don't mean "grade"). e.g.: [Try Haskell](http://tryhaskell.org), [Try Git](https://learngitbranching.js.org).
|
||
- *Playgrounds* : are online and interactive websites, games or desktop software for learning programming. Write, compile (or run), and share code snippets. Playgrounds often allow you to fork and get your hands dirty by playing with code.
|
||
- *Podcasts and Screencasts* : Podcasts and screencasts.
|
||
- *Problem Sets & Competitive Programming* : A website or software which lets you assess your programming skills by solving simple or complex problems, with or without code review, with or without comparing the results with other users.
|
||
|
||
4. Make sure to follow the [guidelines below](#guidelines) and respect the [Markdown formatting](#formatting) of the files.
|
||
|
||
5. GitHub Actions will run tests to **make sure your lists are alphabetized** and **formatting rules are followed**. **Be sure** to check that your changes pass the tests.
|
||
|
||
|
||
### Guidelines
|
||
|
||
- make sure a book is free. Double-check if needed. It helps the admins if you comment in the PR as to why you think the book is free.
|
||
- we don't accept files hosted on Google Drive, Dropbox, Mega, Scribd, Issuu and other similar file upload platforms
|
||
- insert your links in alphabetical order, as described [below](#alphabetical-order).
|
||
- use the link with the most authoritative source (meaning the author's website is better than the editor's website, which is better than a third-party website)
|
||
- no file hosting services (this includes (but is not limited to) Dropbox and Google Drive links)
|
||
- always prefer a `https` link over a `http` one -- as long as they are on the same domain and serve the same content
|
||
- on root domains, strip the trailing slash: `http://example.com` instead of `http://example.com/`
|
||
- always prefer the shortest link: `http://example.com/dir/` is better than `http://example.com/dir/index.html`
|
||
- no URL shortener links
|
||
- usually prefer the "current" link over the "version" one: `http://example.com/dir/book/current/` is better than `http://example.com/dir/book/v1.0.0/index.html`
|
||
- if a link has an expired certificate/self-signed certificate/SSL issue of any other kind:
|
||
1. *replace it* with its `http` counterpart if possible (because accepting exceptions can be complicated on mobile devices).
|
||
2. *leave it* if no `http` version is available but the link is still accessible through `https` by adding an exception to the browser or ignoring the warning.
|
||
3. *remove it* otherwise.
|
||
- if a link exists in multiple formats, add a separate link with a note about each format
|
||
- if a resource exists at different places on the Internet
|
||
- use the link with the most authoritative source (meaning author's website is better than editor's website is better than third-party website)
|
||
- if they link to different editions, and you judge these editions are different enough to be worth keeping them, add a separate link with a note about each edition (see [Issue #2353](https://github.com/EbookFoundation/free-programming-books/issues/2353) to contribute to the discussion on formatting).
|
||
- prefer atomic commits (one commit by addition/deletion/modification) over bigger commits. No need to squash your commits before submitting a PR. (We will never enforce this rule as it's just a matter of convenience for the maintainers)
|
||
- if the book is older, include the publication date with the title.
|
||
- include the author name or names where appropriate. You can shorten author lists with "`et al.`".
|
||
- if the book is not finished, and is still being worked on, add the "`in process`" notation, as described [below](#in_process).
|
||
- if a resource is restored using the [*Internet Archive's Wayback Machine*](https://web.archive.org) (or similar), add the "`archived`" notation, as described [below](#archived). The best versions to use are recent and complete.
|
||
- if an email address or account setup is requested before download is enabled, add language-appropriate notes in parentheses, e.g.: `(email address *requested*, not required)`.
|
||
|
||
|
||
### Formatting
|
||
|
||
- All lists are `.md` files. Try to learn [Markdown](https://guides.github.com/features/mastering-markdown/) syntax. It's simple!
|
||
- All the lists start with an Index. The idea is to list and link all sections and subsections there. Keep it in alphabetical order.
|
||
- Sections are using level 3 headings (`###`), and subsections are level 4 headings (`####`).
|
||
|
||
The idea is to have:
|
||
|
||
- `2` empty lines between last link and new section.
|
||
- `1` empty line between heading & first link of its section.
|
||
- `0` empty line between two links.
|
||
- `1` empty line at the end of each `.md` file.
|
||
|
||
Example:
|
||
|
||
```text
|
||
[...]
|
||
* [An Awesome Book](http://example.com/example.html)
|
||
(blank line)
|
||
(blank line)
|
||
### Example
|
||
(blank line)
|
||
* [Another Awesome Book](http://example.com/book.html)
|
||
* [Some Other Book](http://example.com/other.html)
|
||
```
|
||
|
||
- Don't put spaces between `]` and `(`:
|
||
|
||
```text
|
||
BAD : * [Another Awesome Book] (http://example.com/book.html)
|
||
GOOD: * [Another Awesome Book](http://example.com/book.html)
|
||
```
|
||
|
||
- If you include the author, use ` - ` (a dash surrounded by single spaces):
|
||
|
||
```text
|
||
BAD : * [Another Awesome Book](http://example.com/book.html)- John Doe
|
||
GOOD: * [Another Awesome Book](http://example.com/book.html) - John Doe
|
||
```
|
||
|
||
- Put a single space between the link and its format:
|
||
|
||
```text
|
||
BAD : * [A Very Awesome Book](https://example.org/book.pdf)(PDF)
|
||
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) (PDF)
|
||
```
|
||
|
||
- Author comes before format:
|
||
|
||
```text
|
||
BAD : * [A Very Awesome Book](https://example.org/book.pdf)- (PDF) Jane Roe
|
||
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) - Jane Roe (PDF)
|
||
```
|
||
|
||
- Multiple formats (We prefer a single link for each resource. When there is no single link with easy access to different formats, multiple links may make sense. But every link we add creates maintenance burden so we try to avoid it.):
|
||
|
||
```text
|
||
BAD : * [Another Awesome Book](http://example.com/)- John Doe (HTML)
|
||
BAD : * [Another Awesome Book](https://downloads.example.org/book.html)- John Doe (download site)
|
||
GOOD: * [Another Awesome Book](http://example.com/) - John Doe (HTML) [(PDF, EPUB)](https://downloads.example.org/book.html)
|
||
```
|
||
|
||
- Include publication year in title for older books:
|
||
|
||
```text
|
||
BAD : * [A Very Awesome Book](https://example.org/book.html) - Jane Roe - 1970
|
||
GOOD: * [A Very Awesome Book (1970)](https://example.org/book.html) - Jane Roe
|
||
```
|
||
|
||
- <a id="in_process"></a>In-process books:
|
||
|
||
```text
|
||
GOOD: * [Will Be An Awesome Book Soon](http://example.com/book2.html) - John Doe (HTML) *(:construction: in process)*
|
||
```
|
||
|
||
- <a id="archived"></a>Archived link:
|
||
|
||
```text
|
||
GOOD: * [A Way-backed Interesting Book](https://web.archive.org/web/20211016123456/http://example.com/) - John Doe (HTML) *(:card_file_box: archived)*
|
||
```
|
||
|
||
- <a id="license"></a>Free Licenses (While we include resources that are "All Rights Reserved" but free to read, we encourage the use of free licenses, such as Creative Commons):
|
||
|
||
```text
|
||
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) - Jane Roe (PDF) (CC BY-SA)
|
||
```
|
||
|
||
Supported Licences (no versioning):
|
||
|
||
- `CC BY` 'Creative Commons attribution'
|
||
- `CC BY-NC` 'Creative Commons non-commercial'
|
||
- `CC BY-SA` 'Creative Commons share-alike'
|
||
- `CC BY-NC-SA` 'Creative Commons non-commercial, share-alike'
|
||
- `CC BY-ND` 'Creative Commons no-derivatives'
|
||
- `CC BY-NC-ND` 'Creative Commons non-commercial, no-derivatives'
|
||
- `GFDL` 'Gnu Free Documentation License'
|
||
|
||
|
||
### Alphabetical order
|
||
|
||
- When there are multiple titles beginning with the same letter order them by the second, and so on. For example: `aa` comes before `ab`.
|
||
- `one two` comes before `onetwo`
|
||
|
||
If you see a misplaced link, check the linter error message to know which lines should be swapped.
|
||
|
||
|
||
### Notes
|
||
|
||
While the basics are relatively simple, there is a great diversity in the resources we list. Here are some notes on how we deal with this diversity.
|
||
|
||
|
||
#### Metadata
|
||
|
||
Our lists provide a minimal set of metadata: titles, URLs, creators, platforms, and access notes.
|
||
|
||
|
||
##### Titles
|
||
|
||
- No invented titles. We try to take titles from the resources themselves; contributors are admonished not to invent titles or use them editorially if this can be avoided. An exception is for older works; if they are primarily of historical interest, a year in parentheses appended to the title helps users know if they are of interest.
|
||
- No ALLCAPS titles. Usually title case is appropriate, but when doubt use the capitalization from the source
|
||
- No emojis.
|
||
|
||
|
||
##### URLs
|
||
|
||
- We don't permit shortened URLs.
|
||
- Tracking codes must be removed from the URL.
|
||
- International URLs should be escaped. Browser bars typically render these to Unicode, but use copy and paste, please.
|
||
- Secure (`https`) URLs are always preferred over non-secure (`http`) urls where HTTPS has been implemented.
|
||
- We don't like URLs that point to webpages that don't host the listed resource, but instead point elsewhere.
|
||
|
||
|
||
##### Creators
|
||
|
||
- We want to credit the creators of free resources where appropriate, including translators!
|
||
- For translated works the original author should be credited. We recommend using [MARC relators](https://loc.gov/marc/relators/relaterm.html) to credit creators other than authors, as in this example:
|
||
|
||
```markdown
|
||
* [A Translated Book](http://example.com/book.html) - John Doe, `trl.:` Mike The Translator
|
||
```
|
||
|
||
here, the annotation `trl.:` uses the MARC relator code for "translator".
|
||
- Use a comma `,` to delimit each item in the author list.
|
||
- You can shorten author lists with "`et al.`".
|
||
- We do not permit links for Creators.
|
||
- For compilation or remixed works, the "creator" may need a description. For example, "GoalKicker" or "RIP Tutorial" books are credited as "`Compiled from StackOverflow documentation`".
|
||
- We do not include honorifics such as "Prof." or "Dr." in creator names.
|
||
|
||
|
||
##### Time-limited Courses and Trials
|
||
|
||
- We don't list things that we'll need to remove in six months.
|
||
- If a course has a limited enrollment period or duration, we won't list it.
|
||
- We can't list resources that are free for a limited period.
|
||
|
||
|
||
##### Platforms and Access Notes
|
||
|
||
- Courses. Especially for our course lists, the platform is an important part of the resource description. This is because course platforms have different affordances and access models. While we usually won't list a book that requires registration, many course platforms have affordances that don't work without some sort of account. Example course platforms include Coursera, EdX, Udacity, and Udemy. When a course depends on a platform, the platform name should be listed in parentheses.
|
||
- YouTube. We have many courses which consist of YouTube playlists. We do not list YouTube as a platform, we try to list the YouTube creator, which is often a sub-platform.
|
||
- YouTube videos. We usually don't link to individual YouTube videos unless they are more than an hour long and are structured like a course or a tutorial. If this is the case, be sure to make a note of it in the PR description.
|
||
- No shortened (i.e. youtu.be/xxxx) links!
|
||
- Leanpub. Leanpub hosts books with a variety of access models. Sometimes a book can be read without registration; sometimes a book requires a Leanpub account for free access. Given quality of the books and the mixture and fluidity of Leanpub access models, we permit listing of the latter with the access note `*(Leanpub account or valid email requested)*`.
|
||
|
||
|
||
#### Genres
|
||
|
||
The first rule in deciding which list a resource belongs in is to see how the resource describes itself. If it calls itself a book, then maybe it's a book.
|
||
|
||
|
||
##### Genres we don't list
|
||
|
||
Because the Internet is vast, we don't include in our lists:
|
||
|
||
- blogs
|
||
- blog posts
|
||
- articles
|
||
- websites (except for those that host LOTS of items that we list).
|
||
- videos that aren't courses or screencasts.
|
||
- book chapters
|
||
- teaser samples from books
|
||
- IRC or Telegram channels
|
||
- Slacks or mailing lists
|
||
|
||
Our competitive programming lists are not as strict about these exclusions. The scope of the repo is determined by the community; if you want to suggest a change or addition to the scope, please use an issue to make the suggestion.
|
||
|
||
|
||
##### Books vs. Other Stuff
|
||
|
||
We're not that fussy about book-ness. Here are some attributes that signify that a resource is a book:
|
||
|
||
- it has an ISBN (International Standard Book Number)
|
||
- it has a Table of Contents
|
||
- a downloadable version is offered, especially ePub files.
|
||
- it has editions
|
||
- it doesn't depend on interactive content or videos
|
||
- it tries to comprehensively cover a topic
|
||
- it's self-contained
|
||
|
||
There are lots of books that we list that don't have these attributes; it can depend on context.
|
||
|
||
|
||
##### Books vs. Courses
|
||
|
||
Sometimes these can be hard to distinguish!
|
||
|
||
Courses often have associated textbooks, which we would list in our books lists. Courses have lectures, exercises, tests, notes or other didactic aids. A single lecture or video by itself is not a course. A PowerPoint is not a course.
|
||
|
||
|
||
##### Interactive Tutorials vs. Other stuff
|
||
|
||
If you can print it out and retain its essence, it's not an Interactive Tutorial.
|
||
|
||
|
||
### Automation
|
||
|
||
- Formatting rules enforcement is automated via [GitHub Actions](https://github.com/features/actions) using [fpb-lint](https://github.com/vhf/free-programming-books-lint) (see [`.github/workflows/fpb-lint.yml`](../.github/workflows/fpb-lint.yml))
|
||
- URL validation uses [awesome_bot](https://github.com/dkhamsing/awesome_bot)
|
||
- To trigger URL validation, push a commit that includes a commit message containing `check_urls=file_to_check`:
|
||
|
||
```properties
|
||
check_urls=free-programming-books.md free-programming-books-en.md
|
||
```
|
||
|
||
- You may specify more than one file to check, using a single space to separate each entry.
|
||
- If you specify more than one file, results of the build are based on the result of the last file checked. You should be aware that you may get passing green builds due to this so be sure to inspect the build log at the end of the Pull Request by clicking on "Show all checks" -> "Details".
|
||
|
||
|
||
### Fixing RTL/LTR linter errors
|
||
|
||
If you run the RTL/LTR Markdown Linter (on `*-ar.md`, `*-he.md`, `*-fa.md`, `*-ur.md` files) and see errors or warnings:
|
||
|
||
- **LTR words** (e.g. “HTML”, “JavaScript”) in RTL text: append `‏` immediately after each LTR segment;
|
||
- **LTR symbols** (e.g. “C#”, “C++”): append `‎` immediately after each LTR symbol;
|
||
|
||
#### Examples
|
||
|
||
**BAD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [كتاب الأمثلة في R](URL) - John Doe (PDF)
|
||
</div>
|
||
```
|
||
**GOOD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [كتاب الأمثلة في R‏](URL) - John Doe‏ (PDF)
|
||
</div>
|
||
```
|
||
---
|
||
**BAD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [Tech Podcast - بودكاست المثال](URL) – Ahmad Hasan, محمد علي
|
||
</div>
|
||
```
|
||
**GOOD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [Tech Podcast - بودكاست المثال](URL) – Ahmad Hasan,‏ محمد علي
|
||
</div>
|
||
```
|
||
---
|
||
**BAD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [أساسيات C#](URL)
|
||
</div>
|
||
```
|
||
**GOOD**
|
||
```html
|
||
<div dir="rtl" markdown="1">
|
||
* [أساسيات C#‎](URL)
|
||
</div>
|
||
```
|