Ocideck/lib/services/export_metadata.dart
Brenno de Winter 173f1a3f26
Some checks are pending
CI / Format · Analyze · Test (push) Waiting to run
CI / Format · Analyze · Test (pull_request) Waiting to run
Add TLP classification enforcement with visual marking and export metadata.
Extend export gates with optional floor and required classification, stamp PDF/PPTX/HTML metadata, and show banners and watermarks WYSIWYG across editor, presenter, and export.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 10:35:55 +02:00

70 lines
2 KiB
Dart

import '../models/deck.dart';
/// Producer string embedded in PDF/PPTX metadata.
const kOciDeckProducer = 'OciDeck 1.0.0';
/// Document metadata stamped into PDF, PPTX and HTML exports.
class ExportDocumentMetadata {
final String title;
final String author;
final String organization;
final String description;
final String keywords;
final TlpLevel tlp;
const ExportDocumentMetadata({
this.title = '',
this.author = '',
this.organization = '',
this.description = '',
this.keywords = '',
this.tlp = TlpLevel.none,
});
factory ExportDocumentMetadata.fromDeck(Deck deck) => ExportDocumentMetadata(
title: deck.title,
author: deck.author,
organization: deck.organization,
description: deck.description,
keywords: deck.keywords,
tlp: deck.tlp,
);
/// Fallback title when [title] is empty.
String displayTitle(String fallback) =>
title.trim().isNotEmpty ? title.trim() : fallback;
/// PDF/PPTX Subject — classificatie vooraan wanneer gezet.
String subject(String fallbackTitle) {
final name = displayTitle(fallbackTitle);
if (tlp == TlpLevel.none) return name;
return '${tlp.label}$name';
}
/// Comma-separated keywords for PDF Info dict and PPTX core props.
String exportKeywords() {
final parts = <String>[];
final deckKeywords = keywords.trim();
if (deckKeywords.isNotEmpty) parts.add(deckKeywords);
if (tlp != TlpLevel.none) {
parts.addAll(['TLP', tlp.label, tlp.key]);
}
parts.add('OciDeck');
return parts.join(', ');
}
/// dc:creator / PDF Author — auteur, anders organisatie.
String get documentAuthor {
if (author.trim().isNotEmpty) return author.trim();
if (organization.trim().isNotEmpty) return organization.trim();
return 'OciDeck';
}
String get producer => kOciDeckProducer;
String? get htmlDescription =>
description.trim().isNotEmpty ? description.trim() : null;
String? get htmlClassification =>
tlp == TlpLevel.none ? null : tlp.label;
}