From 2d8be6f0ddedc6ecbaa52fb5727c2ce51aac5a9f Mon Sep 17 00:00:00 2001 From: Brenno de Winter Date: Sun, 7 Jun 2026 12:19:56 +0200 Subject: [PATCH] Add project docs, EUPL licence, and open-source licence check Documentation & licensing: - Add the EUPL-1.2 licence (LICENSE.md) and set the project licence; refresh the README (name origin wink, updated feature list, documentation index). - Add CONTRIBUTING, SECURITY, CODE_OF_CONDUCT, CHANGELOG, AUTHORS, and THIRD_PARTY_NOTICES, plus docs/ (ARCHITECTURE, BUILD, USER_GUIDE, SHORTCUTS, LICENSE_COMPLIANCE) and .github/ (CI workflow, issue/PR templates). - Bring docs/FILE_FORMAT.md in line with current behaviour (code & chart slides, per-slide TLP comment, annotation .ink.json sidecar, chart data/ CSVs). Open-source compliance: - Add tool/check_licenses.dart and a `make licenses` target (wired into check-full and CI) that verifies every resolved dependency uses a recognised open-source licence. A scan of all 151 packages and bundled assets found only OSI-approved licences. Charts (Fase 1.1): - Replace the chart CSV textarea with an in-app editable data grid (editable series/labels/values, add/remove row & column, read-only when linked). - Centralize the linked-CSV directory name (`data/`) in a shared constant. Also normalize formatting repo-wide with `dart format` and fix one curly-braces lint, so `make check` and CI are green. Co-Authored-By: Claude Opus 4.8 --- .github/ISSUE_TEMPLATE/bug_report.md | 34 ++ .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/feature_request.md | 23 ++ .github/PULL_REQUEST_TEMPLATE.md | 24 ++ .github/workflows/ci.yml | 36 ++ AUTHORS.md | 18 + CHANGELOG.md | 49 +++ CODE_OF_CONDUCT.md | 65 ++++ CONTRIBUTING.md | 84 +++++ LICENSE.md | 290 ++++++++++++++++ Makefile | 15 +- README.md | 59 +++- SECURITY.md | 45 +++ THIRD_PARTY_NOTICES.md | 74 ++++ docs/ARCHITECTURE.md | 120 +++++++ docs/BUILD.md | 82 +++++ docs/FILE_FORMAT.md | 103 +++++- docs/LICENSE_COMPLIANCE.md | 66 ++++ docs/SHORTCUTS.md | 57 ++++ docs/USER_GUIDE.md | 107 ++++++ lib/l10n/app_localizations.dart | 63 +++- lib/models/annotation.dart | 10 +- lib/models/chart.dart | 3 +- lib/services/annotation_codec.dart | 9 +- lib/services/file_service.dart | 4 +- lib/services/marp_html_service.dart | 3 +- lib/widgets/editors/chart_editor.dart | 322 ++++++++++++++---- lib/widgets/panels/editor_panel.dart | 4 +- lib/widgets/presentation/audience_window.dart | 4 +- .../presentation/fullscreen_presenter.dart | 5 +- lib/widgets/slides/slide_preview.dart | 5 +- test/annotation_test.dart | 18 +- test/app_localizations_test.dart | 2 + test/markdown_round_trip_test.dart | 7 +- test/tlp_test.dart | 10 +- tool/check_licenses.dart | 157 +++++++++ 36 files changed, 1857 insertions(+), 125 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/ci.yml create mode 100644 AUTHORS.md create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 SECURITY.md create mode 100644 THIRD_PARTY_NOTICES.md create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/BUILD.md create mode 100644 docs/LICENSE_COMPLIANCE.md create mode 100644 docs/SHORTCUTS.md create mode 100644 docs/USER_GUIDE.md create mode 100644 tool/check_licenses.dart diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..06d874a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Report a problem so we can fix it +title: "[Bug] " +labels: bug +--- + +**Describe the bug** +A clear and concise description of what went wrong. + +**To reproduce** +Steps to reproduce the behaviour: +1. Go to '…' +2. Click on '…' +3. See error + +**Expected behaviour** +What you expected to happen. + +**Screenshots / sample deck** +If applicable, add screenshots or attach a minimal `.md` / `.ocideck` that +triggers the issue. + +**Environment** +- OciDeck version: +- OS and version: +- Flutter version (`flutter --version`): +- Single or dual screen (if presenter-related): + +**Additional context** +Anything else that might help. + +> For **security vulnerabilities**, do not open a public issue — see +> [SECURITY.md](../../SECURITY.md). diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..f7f4323 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/security/advisories + about: Please report security issues privately — see SECURITY.md, do not open a public issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..d7748bc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest an idea or improvement +title: "[Feature] " +labels: enhancement +--- + +**Problem / motivation** +What are you trying to do, and what's missing or awkward today? + +**Proposed solution** +A clear description of what you'd like to happen. + +**Marp / file-format impact** +Does this affect how decks are stored? OciDeck keeps the Marp Markdown the single +source of truth and puts non-Marp data in sidecars — describe how your idea fits +that model (see [docs/FILE_FORMAT.md](../../docs/FILE_FORMAT.md)). + +**Alternatives considered** +Any alternative solutions or features you've considered. + +**Additional context** +Mockups, examples, or links. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..007f592 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ +## Summary + + + +## Changes + + + +- + +## Checklist + +- [ ] `make check` passes (format-check, analyze, full test suite). +- [ ] Added/updated tests for the behaviour I changed. +- [ ] New UI strings go through `context.l10n.d('…')` **and** are translated in + every supported language (nl/en/it/de/fr/es/fy/pap). +- [ ] If I changed how anything is stored, I updated + [`docs/FILE_FORMAT.md`](../docs/FILE_FORMAT.md). +- [ ] Docs updated where relevant (README / docs/). + +## Notes for reviewers + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..95520ca --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: CI + +on: + push: + branches: ["**"] + pull_request: + +jobs: + check: + name: Format · Analyze · Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: 3.44.1 + cache: true + + - name: Flutter version + run: flutter --version + + - name: Install dependencies + run: flutter pub get + + # The same quality gate developers run locally: + # format-check + flutter analyze + the full test suite. + - name: Quality gate (make check) + run: make check + + # Fail the build if any dependency is not open source. + - name: Licence compliance (make licenses) + run: make licenses diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..ab04291 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,18 @@ +# Authors + +OciDeck is created and maintained by: + +- **Brenno de Winter** + +The name is a wink: *Oci* comes from the **Ocicats** (Brenno's cats) and *Deck* +is short for a presentation deck. + +## Contributors + +Thanks to everyone who has contributed code, translations, documentation, bug +reports, and ideas. (Add yourself here in your first pull request.) + +--- + +OciDeck also stands on the shoulders of open-source software; see +[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) for the components it builds on. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..78e888c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,49 @@ +# Changelog + +All notable changes to OciDeck are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and the project aims to follow [Semantic Versioning](https://semver.org/). + +## [Unreleased] + +### Added +- **Source-code slides** — a dark "code sheet" with per-language syntax + highlighting, stored as a fenced code block. +- **Charts** — bar, line, and pie chart slides. Data is entered in an in-app grid + or imported from CSV; the spec is stored as JSON in a ```chart block. Data can + stay inline or be linked to a CSV in a separate `data/` directory. Rendered + natively in-app (preview, presenter, PDF, PPTX) and as self-contained SVG in + the HTML export. +- **Per-slide TLP classification** — each slide can carry its own Traffic Light + Protocol level; slides classified stricter than the level the deck is shown at + are withheld when presenting and exporting. +- **Dual-screen presenter** — on a second display the beamer shows the slide + while the laptop shows the presenter view (current/next slide, notes, timer), + kept in sync over method channels. +- **Annotation layer** — draw on slides while presenting (pen, highlighter, + eraser, laser pointer). Kept fully separate from the Marp Markdown, mirrored + live to the beamer, and persisted in a `.ink.json` sidecar. +- **App theming** — customizable app appearance profiles, including a dark + interface. +- Project documentation: contributing guide, security policy, architecture and + build notes, user guide, keyboard-shortcut reference, third-party notices, and + the EUPL-1.2 licence text. + +### Changed +- Slide transitions in the presenter no longer flash a black frame (neighbour + images are precached and `gaplessPlayback` is enabled) — important for + recording. + +## [1.0.0] + +### Added +- Initial release: structured, slide-by-slide editor for Marp presentations with + typed slide templates, live preview, fullscreen presenter, deck-wide TLP + marking, media handling, import, and export to Marp Markdown, PDF, PPTX, and + self-contained HTML. Decks save as a self-contained project/package with copied + assets. Localized in Dutch, English, Italian, German, French, Spanish, Frisian, + and Papiamento. + +[Unreleased]: https://example.com/ocideck/compare/v1.0.0...HEAD +[1.0.0]: https://example.com/ocideck/releases/tag/v1.0.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..5345d2e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,65 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +- Demonstrating empathy and kindness toward other people. +- Being respectful of differing opinions, viewpoints, and experiences. +- Giving and gracefully accepting constructive feedback. +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience. +- Focusing on what is best not just for us as individuals, but for the overall + community. + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery, and sexual attention or advances of + any kind. +- Trolling, insulting or derogatory comments, and personal or political attacks. +- Public or private harassment. +- Publishing others' private information, such as a physical or email address, + without their explicit permission. +- Other conduct which could reasonably be considered inappropriate in a + professional setting. + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement via the +repository's private contact channels (for example, a GitHub security advisory or +direct message to the maintainer). All complaints will be reviewed and +investigated promptly and fairly. Community leaders are obligated to respect the +privacy and security of the reporter of any incident. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f894024 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,84 @@ +# Contributing to OciDeck + +Thanks for your interest in improving OciDeck! This document explains how to set +up the project, the quality bar, and how to propose changes. + +By contributing you agree that your contributions are licensed under the project +licence, the **European Union Public Licence v. 1.2 (EUPL-1.2)** — see +[`LICENSE.md`](LICENSE.md). + +## Prerequisites + +- **Flutter** 3.44+ (stable channel) with **Dart 3.12+**. +- A desktop target enabled: **macOS**, **Windows**, or **Linux**. +- `make` (the `Makefile` is the entry point for all quality checks). + +See [`docs/BUILD.md`](docs/BUILD.md) for platform-specific build notes (including +the macOS CocoaPods locale caveat and the vendored plugin forks). + +## Setup + +```sh +make setup # flutter pub get +flutter run -d macos # or -d windows / -d linux +``` + +## The quality gate + +Run this before every push — it is exactly what CI runs: + +```sh +make check # format-check + analyze + full test suite +``` + +Individual steps: + +| Command | What it does | +| --- | --- | +| `make format` | Rewrites Dart files with `dart format`. | +| `make format-check` | Fails if any file needs formatting. | +| `make analyze` | `flutter analyze` (analyzer + lints + type checks). | +| `make test` | The full test suite. | +| `make licenses` | Verify every dependency uses an open-source licence. | +| `make check-full` | `check` plus licence compliance and a dependency-freshness report. | + +Targeted test groups for focused work: + +| Target | Covers | +| --- | --- | +| `make test-contracts` | Markdown generation/parsing, save-load round-trips, migration | +| `make test-preview` | Slide rendering, footers, TLP, inline Markdown, charts | +| `make test-export` | PDF/PPTX export and project file-save behaviour | +| `make test-state` | Providers, undo/redo, search/replace, settings, recovery | +| `make test-services` | Image, caption, description sidecar services | +| `make test-presenter` | Fullscreen presenter navigation and shortcuts | + +## Coding guidelines + +- **Formatting & analysis must pass clean** (`make check`). No analyzer warnings. +- **Architecture**: skim [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) before + larger changes. Keep the Marp Markdown the single source of truth; anything + that isn't plain Marp belongs in a sidecar (see the file format). +- **Localization is enforced.** UI strings go through `context.l10n.d('Nederlandse + brontekst')`. The test `test/app_localizations_test.dart` fails if a literal + `.d('…')` string lacks a translation in **every** supported language + (Dutch is the source; en/it/de/fr/es/fy/pap need an entry). Add your strings to + `lib/l10n/app_localizations.dart` for all languages, or the suite goes red. +- **Tests**: add or update tests for behaviour you change — especially the + Markdown round-trip and any file-format change. +- **File format**: if you change how anything is stored, update + [`docs/FILE_FORMAT.md`](docs/FILE_FORMAT.md) in the same change. + +## Proposing changes + +1. Branch from the default branch; keep each branch/PR focused on one topic. +2. Write clear commit messages (imperative subject, a short body explaining the + *why*). +3. Make sure `make check` is green. +4. Open a pull request describing the change and linking any related issue. Fill + in the PR template checklist. + +## Reporting bugs and requesting features + +Use the GitHub issue templates. For **security issues, do not open a public +issue** — follow [`SECURITY.md`](SECURITY.md). diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..cf8680f --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,290 @@ + + +# European Union Public Licence v. 1.2 + +EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the 'EUPL') applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + +> Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +## 1. Definitions + +In this Licence, the following terms have the following meaning: + +- **The Licence**: this Licence. +- **The Original Work**: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. +- **Derivative Works**: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. +- **The Work**: the Original Work or its Derivative Works. +- **The Source Code**: the human-readable form of the Work which is the most + convenient for people to study and modify. +- **The Executable Code**: any code which has generally been compiled and which + is meant to be interpreted by a computer as a program. +- **The Licensor**: the natural or legal person that distributes or communicates + the Work under the Licence. +- **Contributor(s)**: any natural or legal person who modifies the Work under + the Licence, or otherwise contributes to the creation of a Derivative Work. +- **The Licensee** or **'You'**: any natural or legal person who makes any usage + of the Work under the terms of the Licence. +- **Distribution** or **Communication**: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +## 2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +## 3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work along +with each copy of the Work that the Licensor distributes or indicates, in a +notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +## 4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +## 5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +**Attribution right**: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +**Copyleft clause**: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence unless +the Original Work is expressly distributed only under this version of the Licence +— for example by communicating 'EUPL v. 1.2 only'. The Licensee (becoming +Licensor) cannot offer or impose any additional terms or conditions on the Work +or Derivative Work that alter or restrict the terms of the Licence. + +**Compatibility clause**: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, 'Compatible +Licence' refers to the licences listed in the Appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible Licence +shall prevail. + +**Provision of Source Code**: When distributing or communicating copies of the +Work, the Licensee will provide a machine-readable copy of the Source Code or +indicate a repository where this Source will be easily and freely available for +as long as the Licensee continues to distribute or communicate the Work. + +**Legal Protection**: This Licence does not grant permission to use the trade +names, trademarks, service marks, or names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +## 6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +## 7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +'bugs' inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an 'as is' basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +## 8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +## 9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by the +fact You have accepted any warranty or additional liability. + +## 10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon 'I agree' +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +## 11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a remote +location) the distribution channel or media (for example, a website) must at +least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +## 12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has received +the Work from the Licensee under the Licence, provided such persons remain in +full compliance with the Licence. + +## 13. Miscellaneous + +Without prejudice to Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable law, +this will not affect the validity or enforceability of the Licence as a whole. +Such provision will be construed or reformed so as necessary to make it valid and +enforceable. + +The European Commission may put into force translations or new versions of the +Licence, so far this is required and reasonable, without reducing the scope of +the rights granted by the Licence. New versions of the Licence will be published +with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +## 14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court of + Justice of the European Union, as laid down in article 272 of the Treaty on the + Functioning of the European Union, +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +## 15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +--- + +## Appendix + +**'Compatible Licences' according to Article 5 EUPL are:** + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide the +rights granted in Article 2 of this Licence and protect the covered Source Code +from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. diff --git a/Makefile b/Makefile index b1ed97d..64db7f6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: setup format format-check analyze test test-contracts test-preview test-export test-state test-services test-presenter deps-outdated check check-full help +.PHONY: setup format format-check analyze test test-contracts test-preview test-export test-state test-services test-presenter deps-outdated licenses check check-full help help: @echo "OciDeck quality targets:" @@ -11,6 +11,7 @@ help: @echo " make test-services Caption/description/image service tests." @echo " make test-presenter Fullscreen presenter interaction tests." @echo " make deps-outdated Advisory dependency freshness report." + @echo " make licenses Verify all dependencies use open-source licences." # Install Flutter/Dart dependencies. setup: @@ -105,12 +106,20 @@ deps-outdated: @echo "Failure means: inspect network/tooling first; outdated packages are not necessarily regressions." flutter pub outdated +# Open-source licence compliance check for all resolved dependencies. +licenses: + @echo "== OciDeck check: licences ==" + @echo "Command: dart run tool/check_licenses.dart" + @echo "Covers: licence of every resolved Dart/Flutter package (direct + transitive)." + @echo "Failure means: a dependency uses an unrecognised or non-open-source licence — review it." + dart run tool/check_licenses.dart + # Full local quality gate. Intended for humans, CI logs, and LLM-assisted debugging. check: format-check analyze test @echo "== OciDeck check complete ==" @echo "Validated: formatting, static analysis, and the full Flutter test suite." # Extended local check with advisory dependency freshness after the required gate. -check-full: check deps-outdated +check-full: check licenses deps-outdated @echo "== OciDeck extended check complete ==" - @echo "Validated: required quality gate plus dependency freshness report." + @echo "Validated: required quality gate, licence compliance, and dependency freshness." diff --git a/README.md b/README.md index 8dd8921..b64ea77 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,27 @@ # OciDeck -A desktop application for building [Marp](https://marp.app/) presentations through a structured, slide-by-slide editor — no raw Markdown wrangling required. Compose decks from typed slide templates (title, bullets, quotes, tables, images, video, audio), preview them live, present them fullscreen, and export to Marp Markdown, PDF, and PPTX. +A desktop application for building [Marp](https://marp.app/) presentations through a structured, slide-by-slide editor — no raw Markdown wrangling required. Compose decks from typed slide templates (title, bullets, quotes, tables, images, video, audio, source code, charts), preview them live, present them fullscreen — even across two screens — and export to Marp Markdown, PDF, PPTX, and self-contained HTML. Built with Flutter for macOS, Windows, and Linux. +> **What's in a name?** *OciDeck* is a small wink: **Oci** is borrowed from the *Ocicats* — the cats of [Brenno de Winter](https://nl.wikipedia.org/wiki/Brenno_de_Winter) — and **Deck** is short for a presentation deck. So: the cats' presentation tool. + ## Features -- **Structured slide editors** — dedicated editors per slide type: title, bullets, two-column bullets, bullets + image, single/two images, quote, table, section divider, image-only, video, audio, and free-form Markdown. +- **Structured slide editors** — dedicated editors per slide type: title, bullets, two-column bullets, bullets + image, single/two images, quote, table, section divider, image-only, video, audio, source code, charts, and free-form Markdown. +- **Source-code slides** — a dark "code sheet" with syntax highlighting per language, stored as a fenced code block. +- **Charts** — bar, line, and pie charts rendered natively (preview, presenter, PDF, PPTX) and as self-contained SVG in the HTML export. Data is entered in an in-app grid or imported from CSV; the spec is stored as JSON in the Markdown, with optional linking to a CSV kept in a tidy `data/` directory. - **Live preview** — see each slide rendered as you edit, with inline Markdown, footers, and TLP (Traffic Light Protocol) marking. Free-Markdown slides render fenced code with syntax highlighting and `$…$` / `$$…$$` LaTeX math. -- **Fullscreen presenter** — keyboard-driven navigation, presenter view, and a slide-grid overview. +- **Traffic Light Protocol** — a deck-wide classification plus an optional **per-slide TLP level**; slides classified stricter than the level the deck is shown at are automatically withheld, both when presenting and exporting. +- **Fullscreen presenter** — keyboard-driven navigation, presenter view, blank screen, auto-advance, and a slide-grid overview. +- **Dual-screen presenter** — when a second display is connected, the beamer shows the slide while the laptop shows the presenter view (current/next slide, notes, timer), kept in sync. +- **Annotation layer** — draw on slides while presenting (pen, highlighter, eraser, laser pointer). Kept as a separate layer that never touches the Marp Markdown, mirrored live to the beamer, and saved in a `.ink.json` sidecar. - **Media handling** — drag-and-drop images, an image carousel picker, captions, and descriptions stored as sidecar metadata. -- **Import / export** — round-trips Marp Markdown, imports existing slides, and exports to PDF, PPTX (with speaker notes), and a self-contained offline HTML deck (code highlighting, math, and mermaid diagrams render in the browser). Decks are saved as a self-contained package with copied assets. +- **Import / export** — round-trips Marp Markdown, imports existing slides, and exports to PDF, PPTX (with speaker notes), and a self-contained offline HTML deck (code highlighting, math, charts, and mermaid diagrams render in the browser). Decks are saved as a self-contained package with copied assets. - **Productivity** — find & replace, slide finder, undo/redo, skip-slide state, multi-select with bulk copy-to-another-deck / delete / skip, and tabbed multi-deck editing. `Ctrl/Cmd+O` opens, `Ctrl/Cmd+S` saves. - **Crash recovery** — automatic snapshots so work survives an unexpected exit. -- **Theming** — a bundled Marp CSS theme (`assets/themes/ocideck.css`) and a bundled EB Garamond font (no network fetch). +- **Theming** — customizable deck style profiles and app appearance (including a dark interface), a bundled Marp CSS theme (`assets/themes/ocideck.css`), and a bundled EB Garamond font (no network fetch). +- **Localized** — Dutch, English, Italian, German, French, Spanish, Frisian, and Papiamento. ## Requirements @@ -69,11 +77,44 @@ State is managed with [Riverpod](https://riverpod.dev/). ## File format Presentations are saved as standard, Marp-compatible Markdown (`.md`) with a -defined project folder layout and an optional portable `.ocideck` package. The -full specification — front matter, per-slide markup, style profile, captions, -and the package format — is documented in +defined project folder layout and an optional portable `.ocideck` package. +Anything that isn't plain Marp is kept in side files so the `.md` stays pure and +portable: image captions, the annotation layer (`.ink.json`), and linked chart +data (`data/*.csv`). The full specification — front matter, per-slide markup, +style profile, sidecars, and the package format — is documented in [`docs/FILE_FORMAT.md`](docs/FILE_FORMAT.md). +## Documentation + +| Document | What it covers | +| --- | --- | +| [User Guide](docs/USER_GUIDE.md) | Using the app: slide types, charts, presenting, exporting, theming | +| [Keyboard shortcuts](docs/SHORTCUTS.md) | Editor and presenter shortcuts | +| [File format](docs/FILE_FORMAT.md) | The Marp Markdown, front matter, sidecars, and `.ocideck` package | +| [Architecture](docs/ARCHITECTURE.md) | How the code fits together (for contributors) | +| [Build & release](docs/BUILD.md) | Building from source and producing distributables | +| [Contributing](CONTRIBUTING.md) | Setup, the quality gate, and how to propose changes | +| [Security policy](SECURITY.md) | How to report a vulnerability | +| [Changelog](CHANGELOG.md) | Notable changes per version | +| [Third-party notices](THIRD_PARTY_NOTICES.md) | Bundled components and their licences | +| [Licence compliance](docs/LICENSE_COMPLIANCE.md) | Open-source policy and the `make licenses` check | + +## Contributing + +Contributions are welcome! Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) and our +[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md). In short: `make check` must pass, new +UI strings must be translated in all languages, and file-format changes must be +reflected in `docs/FILE_FORMAT.md`. For security issues, see +[`SECURITY.md`](SECURITY.md). + ## License -All rights reserved. _(Update this section if you intend to open-source the project.)_ +Copyright © Brenno de Winter. + +OciDeck is licensed under the **European Union Public Licence v. 1.2 (EUPL-1.2)**. +You may use, study, share, and modify the software under the terms of that +licence. The full text is in [`LICENSE.md`](LICENSE.md); the official versions in +all EU languages are available from the +[EUPL collection](https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12). + +SPDX-License-Identifier: `EUPL-1.2` diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..df4b11c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,45 @@ +# Security Policy + +## Reporting a vulnerability + +**Please do not report security vulnerabilities through public GitHub issues, +discussions, or pull requests.** + +Instead, report them privately via GitHub's **"Report a vulnerability"** button +under the repository's **Security** tab (Security Advisories). If that is not +available to you, contact the maintainer directly and wait for a reply before +disclosing anything publicly. + +When reporting, please include as much of the following as you can: + +- A description of the issue and its impact. +- Steps to reproduce (a minimal deck or input file if relevant). +- The OciDeck version, operating system, and Flutter version. +- Any proof-of-concept, logs, or screenshots. + +## What to expect + +- **Acknowledgement** of your report as quickly as we reasonably can. +- An assessment and, where confirmed, a fix developed under coordinated + (responsible) disclosure. +- Credit for the discovery if you wish — let us know how you would like to be + named. + +We ask that you give us a reasonable opportunity to address the issue before any +public disclosure, and that you avoid privacy violations, data destruction, or +service disruption while researching. + +## Scope notes + +OciDeck is an offline desktop application. Areas of particular interest: + +- Parsing of untrusted decks (`.md`), packages (`.ocideck`), sidecars + (`.ink.json`, captions), and linked CSV data. +- Importing presentations from a URL. +- The HTML export, which inlines third-party JavaScript (marked, highlight.js, + mermaid, MathJax) to render offline. + +## Supported versions + +Security fixes target the latest released version and the default development +branch. Older versions may not receive fixes. diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..d36d68a --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,74 @@ +# Third-Party Notices + +OciDeck is licensed under the EUPL-1.2 (see [`LICENSE.md`](LICENSE.md)). It +builds on, and bundles, third-party components that remain under their own +licences. This file lists them; each component's full licence text is available +from its project or package page. + +## Bundled runtime assets + +Shipped inside the app and embedded into the **offline HTML export** +(`assets/web_export/`) and the UI: + +| Component | Used for | Licence | +| --- | --- | --- | +| [marked](https://github.com/markedjs/marked) | Markdown → HTML in the export | MIT | +| [highlight.js](https://github.com/highlightjs/highlight.js) | Code highlighting in the export | BSD-3-Clause | +| [Mermaid](https://github.com/mermaid-js/mermaid) | Diagrams in the export | MIT (bundles [DOMPurify](https://github.com/cure53/DOMPurify), Apache-2.0 / MPL-2.0) | +| [MathJax](https://github.com/mathjax/MathJax) (`tex-svg.js`) | Math rendering in the export | Apache-2.0 | +| [EB Garamond](https://github.com/octaviopardo/EBGaramond12) font | Bundled deck font | SIL Open Font License 1.1 | + +## Vendored (forked) plugins + +Kept in `third_party/` and wired in via `pubspec.yaml` (path dependency / +`dependency_overrides`). Both are forks of upstream plugins with local native +changes; see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md#vendored-forks). + +| Component | Origin | Licence | Local changes | +| --- | --- | --- | --- | +| `desktop_multi_window` | [MixinNetwork/flutter-plugins](https://github.com/MixinNetwork/flutter-plugins) | MIT | Added native macOS window placement/fullscreen/close methods for the dual-screen presenter | +| `screen_retriever_macos` | [leanflutter/screen_retriever](https://github.com/leanflutter/screen_retriever) | MIT | Packaging fix for recent Xcode/CocoaPods | + +## Dart & Flutter packages + +Direct dependencies (see `pubspec.yaml` for exact version constraints). Each is +distributed under its own OSI-approved licence as published on +[pub.dev](https://pub.dev); most are MIT, BSD-3-Clause, or Apache-2.0. + +- `flutter`, `flutter_localizations` (Flutter SDK — BSD-3-Clause) +- `flutter_riverpod` +- `file_picker` +- `path_provider`, `path` +- `uuid` +- `screen_retriever`, `window_manager` +- `shared_preferences` +- `pasteboard` +- `pdf` +- `archive` +- `video_player` +- `characters` +- `url_launcher` +- `desktop_drop` +- `image` +- `flutter_highlight`, `highlight` +- `flutter_math_fork` +- `wakelock_plus` +- `fl_chart` +- `cupertino_icons` + +> To regenerate an authoritative, version-pinned licence inventory you can use a +> tool such as `flutter pub deps` together with a licence-collection package. + +## Licence audit + +A scan of all resolved Dart/Flutter packages (direct **and** transitive) and the +bundled assets found only OSI-approved open-source licences — MIT, BSD +(2-/3-Clause), Apache-2.0, MPL-2.0, and the SIL Open Font License 1.1. No +proprietary or source-unavailable components are included. (The only MPL-2.0 +dependency is `dbus`, used on Linux.) Re-run such a scan after changing +dependencies. + +Run it yourself with `make licenses` (or `dart run tool/check_licenses.dart`). +The policy, method, and latest result are documented in +[`docs/LICENSE_COMPLIANCE.md`](docs/LICENSE_COMPLIANCE.md). + diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..9ef7b05 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,120 @@ +# OciDeck — Architecture + +A high-level map of how OciDeck is put together, for contributors. For how files +are stored on disk, see [`FILE_FORMAT.md`](FILE_FORMAT.md). + +## Stack + +- **Flutter** desktop app (macOS, Windows, Linux), Dart 3.12+. +- **State**: [Riverpod](https://riverpod.dev/). +- **Storage**: standard Marp Markdown (`.md`) as the single source of truth, with + sidecars for anything that isn't plain Marp. + +## Module layout + +``` +lib/ + models/ # Deck, Slide, Settings/ThemeProfile, Chart, Annotation + services/ # markdown, file, export, image, caption, description, + # recovery, rasterizer, marp_html, annotation_codec + state/ # Riverpod providers: deck, editor, settings, tabs, clipboard + widgets/ # app shell, panels, dialogs, per-type editors, slides, presenter + l10n/ # AppLocalizations (8 languages) + theme/ # app theming +``` + +## Data model + +- **`Deck`** holds metadata, a list of **`Slide`**s, the active **`ThemeProfile`**, + the deck-wide TLP level, and an in-memory **annotation layer** (`Map>`) that is *never* serialized into the Markdown. +- **`Slide`** is a single immutable value with a `SlideType` and typed fields. A + few types reuse `customMarkdown` for their payload: free-Markdown (raw), + `code` (the source), and `chart` (the JSON spec). +- Slide ids are **regenerated on every parse**, so they are stable only within a + session. Anything persisted that must survive a reload (annotations) re-anchors + by slide order + a content fingerprint rather than by id. + +## Markdown round-trip + +`MarkdownService` is the contract: + +- `generateDeck` / `generateSlide` write Marp Markdown. OciDeck extras live in + front-matter keys and `` comments that Marp ignores. +- `parseDeck` / `_parseBlock` read it back. `code` and `chart` slides are detected + by their `_class` and parsed separately (their fenced block would otherwise + confuse the generic line parser). + +This service is heavily covered by the round-trip tests — treat it as the +source-of-truth for the file format and keep `FILE_FORMAT.md` in sync. + +## The two rendering worlds + +Charts, diagrams, and slides are rendered in **two independent places**, which is +the key thing to understand before touching rendering: + +1. **In-app** — `widgets/slides/slide_preview.dart` (`SlidePreviewWidget`) renders + a slide as Flutter widgets. The *same* widget is used for the editor preview, + thumbnails, the fullscreen presenter, and — via `services/slide_rasterizer.dart` + — the **PDF and PPTX** exports (rasterized to images). So anything that must + appear in PDF/PPTX must render here. Charts use `fl_chart`. +2. **HTML export** — `services/marp_html_service.dart` produces a single + self-contained `.html` that renders in a browser using inlined JavaScript + (marked, highlight.js, mermaid, MathJax). Charts are pre-rendered to inline + **SVG in Dart** here (no JS chart library). Fidelity differs from the in-app + renderer by design. + +## Presenter + +`widgets/presentation/fullscreen_presenter.dart` drives presenting: + +- Keyboard navigation, presenter view, blank screen, grid overview, auto-advance, + and the **annotation tools** (pen/highlighter/eraser/laser). +- Neighbour slide images are **precached** and `gaplessPlayback` is on, so slide + changes never flash black (important for screen recording). + +### Dual-screen mode + +When a second display is present (`shouldUseDualScreen`), the presenter runs in +two OS windows: + +- The **laptop** window shows the presenter view. +- A borderless **audience** window (`audience_window.dart`) fills the external + screen with the slide. +- They sync over method channels (`ocideck/audience`, `ocideck/presenter`): + current index, blank state, ink strokes, and the laser pointer. Media plays only + on the beamer to avoid double audio. + +This needs a real second window, which `window_manager` (single-window) can't do, +hence the vendored multi-window fork below. + +## Sidecars (separate layers) + +To keep the `.md` pure Marp, three kinds of data live beside it (see +`FILE_FORMAT.md` §6): + +- **Captions** — `.ocideck_captions.json` (per image, in `images/`). +- **Annotations** — `.ink.json` (`services/annotation_codec.dart`). +- **Linked chart data** — `data/*.csv` (the living source for a chart). + +## Vendored forks + +Two upstream plugins are forked into `third_party/` and wired via `pubspec.yaml` +(path dependency / `dependency_overrides`): + +- **`desktop_multi_window`** (MixinNetwork) — published 0.3.0 dropped the native + window-geometry API. The fork adds macOS `window_setFrame`, + `window_coverScreen` (borderless fill of a chosen screen), and `window_close`, + exposed on `WindowController`. This is what makes the dual-screen audience + window possible. +- **`screen_retriever_macos`** (leanflutter) — a packaging fix for recent + Xcode/CocoaPods. + +If you bump either upstream, re-apply the local changes (they're small and +documented in the diff) and re-test the dual-screen presenter. + +## Localization + +`l10n/app_localizations.dart` holds Dutch source strings (`d('…')`) and +translation maps for en/it/de/fr/es/fy/pap. A test enforces that every literal +`.d('…')` has a translation in every language — add new strings to all maps. diff --git a/docs/BUILD.md b/docs/BUILD.md new file mode 100644 index 0000000..09b91fb --- /dev/null +++ b/docs/BUILD.md @@ -0,0 +1,82 @@ +# OciDeck — Build & Release + +How to build OciDeck from source and produce distributable apps. + +## Prerequisites + +- **Flutter** 3.44+ (stable), **Dart** 3.12+. Check with `flutter --version`. +- A desktop toolchain for your target: + - **macOS**: Xcode + CocoaPods. + - **Windows**: Visual Studio with the "Desktop development with C++" workload. + - **Linux**: see Flutter's Linux desktop prerequisites (GTK, clang, ninja, etc.). +- Enable the desktop target once if needed, e.g. `flutter config --enable-macos-desktop`. + +## Get dependencies + +```sh +make setup # flutter pub get +``` + +OciDeck uses two **vendored plugin forks** under `third_party/`, wired through +`pubspec.yaml` (a path dependency for `desktop_multi_window`) and +`dependency_overrides` (`screen_retriever_macos`, and a pin of +`video_player_avfoundation`). `flutter pub get` resolves these automatically — no +extra steps. See [`ARCHITECTURE.md`](ARCHITECTURE.md#vendored-forks). + +## Run + +```sh +flutter run -d macos # or -d windows / -d linux +``` + +## Quality gate + +```sh +make check # format-check + flutter analyze + full test suite +``` + +## Building release apps + +```sh +flutter build macos --release +flutter build windows --release +flutter build linux --release +``` + +Artifacts land under `build//`. + +### macOS notes + +- **Swift Package Manager is disabled** for this project (`flutter:` → + `config: enable-swift-package-manager: false` in `pubspec.yaml`); CocoaPods is + used instead. The "plugin does not support Swift Package Manager" message + during a build is therefore expected and harmless. +- **`video_player_avfoundation` is pinned** (see `dependency_overrides`) because a + newer release ships a Swift module whose private Objective-C dependency isn't + packaged correctly by CocoaPods on recent Xcode. +- **CocoaPods + Ruby locale**: on some setups `pod install` (run by + `flutter build macos`) fails with `Encoding::CompatibilityError` / + "Unicode Normalization not appropriate for ASCII-8BIT". This is a Ruby/CocoaPods + locale issue, not a project problem. Fix it by forcing a UTF-8 locale: + + ```sh + export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 + flutter build macos --release + ``` + +- **Distribution**: code-sign and notarize the `.app` for distribution outside + the App Store (Developer ID + `notarytool`). This is environment-specific and + not automated here. + +### Windows / Linux notes + +- Windows: distribute the contents of `build/windows/x64/runner/Release/` (or + package with MSIX/an installer). +- Linux: distribute `build/linux/x64/release/bundle/` (or package as a + Flatpak/AppImage/Snap as you prefer). + +## CI + +`.github/workflows/ci.yml` runs `make check` on Ubuntu for every push and pull +request. It does not build native binaries; it validates formatting, static +analysis, and the test suite (which are platform-independent). diff --git a/docs/FILE_FORMAT.md b/docs/FILE_FORMAT.md index bb87f1c..f21c7c7 100644 --- a/docs/FILE_FORMAT.md +++ b/docs/FILE_FORMAT.md @@ -25,9 +25,12 @@ opzichte van de map van het `.md`-bestand. ``` mijn_presentatie/ ├── Mijn_presentatie.md # de presentatie (Marp Markdown) +├── Mijn_presentatie.ink.json # annotatielaag-sidecar (zie §6.2) ├── images/ # gekopieerde afbeeldingen │ ├── foto.png -│ └── .ocideck_captions.json # bijschriften-sidecar (zie §6) +│ └── .ocideck_captions.json # bijschriften-sidecar (zie §6.1) +├── data/ # gekoppelde grafiek-CSV's (zie §6.3) +│ └── omzet.csv ├── logos/ # gekopieerd logo van het stijlprofiel │ └── logo.png ├── media/ # video/audio (alleen in het pakket, zie §7) @@ -42,6 +45,11 @@ De mappen `images/`, `logos/`, `themes/` (en `node_modules/`, `build/`, `.git/`, `.dart_tool/`) worden overgeslagen wanneer OciDeck een map scant op presentaties. +> Naast de `.md` staan **sidecars** die bewust géén onderdeel van de Marp- +> Markdown zijn (zodat het `.md` puur en uitwisselbaar blijft): de +> annotatielaag (`.ink.json`, §6.2), bijschriften (`.ocideck_captions.json`, +> §6.1) en gekoppelde grafiekdata (`data/*.csv`, §6.3). + --- ## 2. Markdown-structuur op hoofdlijnen @@ -134,6 +142,8 @@ JSON heeft deze velden (met standaardwaarden): | `footerText` | `""` | Vrije footertekst; tokens: `{page}`, `{total}`, `{date}`, `{title}`. | | `footerShowPageNumbers` | `false` | Toon "pagina / totaal" rechtsonder. | | `footerPosition` | `right` | `left`/`center`/`right`. | +| `closingSlideEnabled` | `false` | Voeg automatisch een slotslide toe bij presenteren/exporteren. | +| `closingSlideMarkdown` | `"# Bedankt\n\nVragen?"` | Markdown van die slotslide. | Onbekende/ontbrekende velden vallen terug op de standaardwaarden, dus oudere bestanden migreren probleemloos. @@ -159,11 +169,16 @@ De eerste class bepaalt (samen met de inhoud) het **slidetype**: | Quote | `quote` | een `>`-regel aanwezig | | Video | `video` | een `