@jwilleke/ngdpbase-types 0.0.0 → 5.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +16 -2
- package/lib/packages/ngdpbase-types/index.d.ts +32 -0
- package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
- package/lib/packages/ngdpbase-types/testing.js +53 -0
- package/lib/src/cache/CacheDependencies.d.ts +50 -0
- package/lib/src/cache/CacheDependencies.js +50 -0
- package/lib/src/cache/ICacheAdapter.d.ts +86 -0
- package/lib/src/cache/RegionCache.d.ts +171 -0
- package/lib/src/context/ActorContext.d.ts +48 -0
- package/lib/src/context/ActorContext.js +33 -0
- package/lib/src/context/ApiContext.d.ts +194 -0
- package/lib/src/context/ApiContext.js +273 -0
- package/lib/src/context/BaseContext.d.ts +110 -0
- package/lib/src/context/BaseContext.js +143 -0
- package/lib/src/context/JobContext.d.ts +153 -0
- package/lib/src/context/JobContext.js +144 -0
- package/lib/src/context/WikiContext.d.ts +404 -0
- package/lib/src/context/bootActions.d.ts +64 -0
- package/lib/src/context/bootActions.js +111 -0
- package/lib/src/converters/HtmlConverter.d.ts +70 -0
- package/lib/src/converters/IContentConverter.d.ts +94 -0
- package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
- package/lib/src/converters/conversionWarning.d.ts +15 -0
- package/lib/src/converters/ncm/bridge.d.ts +22 -0
- package/lib/src/converters/ncm/existing.d.ts +23 -0
- package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
- package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
- package/lib/src/converters/ncm/fix/index.d.ts +36 -0
- package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
- package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
- package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
- package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
- package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
- package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
- package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
- package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
- package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
- package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
- package/lib/src/converters/ncm/fix/types.d.ts +33 -0
- package/lib/src/converters/ncm/footnotes.d.ts +39 -0
- package/lib/src/converters/ncm/images.d.ts +49 -0
- package/lib/src/converters/ncm/index.d.ts +20 -0
- package/lib/src/converters/ncm/links.d.ts +21 -0
- package/lib/src/converters/ncm/normalize.d.ts +39 -0
- package/lib/src/converters/ncm/placeholder.d.ts +25 -0
- package/lib/src/converters/ncm/tables.d.ts +36 -0
- package/lib/src/converters/ncm/types.d.ts +42 -0
- package/lib/src/http/egressPolicy.d.ts +52 -0
- package/lib/src/http/guardedFetch.d.ts +89 -0
- package/lib/src/http/guardedFetch.js +113 -0
- package/lib/src/http/guardedLookup.d.ts +48 -0
- package/lib/src/http/guardedLookup.js +73 -0
- package/lib/src/http/ssrf.d.ts +83 -0
- package/lib/src/http/ssrf.js +311 -0
- package/lib/src/mail/MailProvider.d.ts +36 -0
- package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
- package/lib/src/managers/AddonsManager.d.ts +691 -0
- package/lib/src/managers/AgentTokenManager.d.ts +269 -0
- package/lib/src/managers/AssetManager.d.ts +116 -0
- package/lib/src/managers/AttachmentManager.d.ts +1032 -0
- package/lib/src/managers/AuthManager.d.ts +1257 -0
- package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
- package/lib/src/managers/BaseManager.d.ts +427 -0
- package/lib/src/managers/BaseManager.js +415 -0
- package/lib/src/managers/CacheManager.d.ts +159 -0
- package/lib/src/managers/CatalogManager.d.ts +235 -0
- package/lib/src/managers/CommentManager.d.ts +75 -0
- package/lib/src/managers/ConfigurationManager.d.ts +747 -0
- package/lib/src/managers/DatabaseManager.d.ts +188 -0
- package/lib/src/managers/DatabaseManager.js +590 -0
- package/lib/src/managers/EmailManager.d.ts +47 -0
- package/lib/src/managers/ExportManager.d.ts +129 -0
- package/lib/src/managers/ExportManager.js +420 -0
- package/lib/src/managers/FootnoteManager.d.ts +118 -0
- package/lib/src/managers/MediaManager.d.ts +279 -0
- package/lib/src/managers/MetricsManager.d.ts +89 -0
- package/lib/src/managers/NotificationManager.d.ts +165 -0
- package/lib/src/managers/OidcManager.d.ts +210 -0
- package/lib/src/managers/OrganizationManager.d.ts +107 -0
- package/lib/src/managers/PageManager.d.ts +1645 -0
- package/lib/src/managers/PersonManager.d.ts +48 -0
- package/lib/src/managers/PluginManager.d.ts +179 -0
- package/lib/src/managers/PluginManager.js +393 -0
- package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
- package/lib/src/managers/RenderingManager.d.ts +358 -0
- package/lib/src/managers/RoleManager.d.ts +134 -0
- package/lib/src/managers/SearchManager.d.ts +402 -0
- package/lib/src/managers/ShareManager.d.ts +251 -0
- package/lib/src/managers/TemplateManager.d.ts +176 -0
- package/lib/src/managers/ThemeManager.d.ts +56 -0
- package/lib/src/managers/UserManager.d.ts +480 -0
- package/lib/src/managers/ValidationManager.d.ts +426 -0
- package/lib/src/managers/VariableManager.d.ts +145 -0
- package/lib/src/middleware/csrf.d.ts +3 -0
- package/lib/src/parsers/LinkParser.d.ts +457 -0
- package/lib/src/parsers/MarkupParser.d.ts +769 -0
- package/lib/src/parsers/context/ParseContext.d.ts +314 -0
- package/lib/src/parsers/data/emoji-map.d.ts +18 -0
- package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
- package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
- package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
- package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
- package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
- package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
- package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
- package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
- package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
- package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
- package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
- package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
- package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
- package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
- package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
- package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
- package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
- package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
- package/lib/src/plugins/types.d.ts +79 -0
- package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
- package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
- package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
- package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
- package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
- package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
- package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
- package/lib/src/providers/BaseDatabaseProvider.js +12 -0
- package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
- package/lib/src/providers/BaseLoggingProvider.js +37 -0
- package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
- package/lib/src/providers/BasePageProvider.d.ts +337 -0
- package/lib/src/providers/BaseProvider.d.ts +98 -0
- package/lib/src/providers/BaseProvider.js +74 -0
- package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
- package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
- package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
- package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
- package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
- package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
- package/lib/src/providers/FileLoggingProvider.js +120 -0
- package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
- package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
- package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
- package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
- package/lib/src/providers/NullCacheProvider.d.ts +72 -0
- package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
- package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
- package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
- package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
- package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
- package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
- package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
- package/lib/src/providers/databaseMigrations.d.ts +8 -0
- package/lib/src/providers/databaseMigrations.js +47 -0
- package/lib/src/providers/jobState.d.ts +99 -0
- package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
- package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
- package/lib/src/providers/sqliteBackup.d.ts +128 -0
- package/lib/src/providers/sqliteBackup.js +365 -0
- package/lib/src/providers/sqliteLocation.d.ts +17 -0
- package/lib/src/providers/sqliteLocation.js +55 -0
- package/lib/src/providers/sqliteMigrations.d.ts +48 -0
- package/lib/src/providers/sqliteMigrations.js +72 -0
- package/lib/src/rendering/githubAlerts.d.ts +22 -0
- package/lib/src/rendering/htmlPolicy.d.ts +76 -0
- package/lib/src/rendering/markdownConverter.d.ts +73 -0
- package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
- package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
- package/lib/src/security/pageActions.d.ts +40 -0
- package/lib/src/security/permissions.generated.d.ts +78 -0
- package/lib/src/types/Asset.d.ts +414 -0
- package/lib/src/types/Catalog.d.ts +61 -0
- package/lib/src/types/Comment.d.ts +11 -0
- package/lib/src/types/Config.d.ts +388 -0
- package/lib/src/types/Organization.d.ts +78 -0
- package/lib/src/types/OrganizationProvider.d.ts +38 -0
- package/lib/src/types/Page.d.ts +220 -0
- package/lib/src/types/Person.d.ts +56 -0
- package/lib/src/types/PersonProvider.d.ts +25 -0
- package/lib/src/types/Policy.d.ts +139 -0
- package/lib/src/types/Policy.js +17 -0
- package/lib/src/types/Provider.d.ts +810 -0
- package/lib/src/types/Role.d.ts +84 -0
- package/lib/src/types/RoleProvider.d.ts +35 -0
- package/lib/src/types/Schema.d.ts +425 -0
- package/lib/src/types/Share.d.ts +172 -0
- package/lib/src/types/Share.js +81 -0
- package/lib/src/types/User.d.ts +304 -0
- package/lib/src/types/Version.d.ts +189 -0
- package/lib/src/types/WikiEngine.d.ts +128 -0
- package/lib/src/types/express.d.ts +120 -0
- package/lib/src/types/express.js +1 -0
- package/lib/src/types/guards.d.ts +78 -0
- package/lib/src/types/heic-decode.d.ts +16 -0
- package/lib/src/types/index.d.ts +19 -0
- package/lib/src/types/linkedom.d.ts +77 -0
- package/lib/src/types/markdown-it-plugins.d.ts +21 -0
- package/lib/src/utils/DeltaStorage.d.ts +118 -0
- package/lib/src/utils/LocaleUtils.d.ts +105 -0
- package/lib/src/utils/LocaleUtils.js +294 -0
- package/lib/src/utils/PageNameMatcher.d.ts +98 -0
- package/lib/src/utils/PathPreflight.d.ts +38 -0
- package/lib/src/utils/PathPreflight.js +50 -0
- package/lib/src/utils/SectionUtils.d.ts +40 -0
- package/lib/src/utils/addonConfigLayer.d.ts +144 -0
- package/lib/src/utils/addonConfigLayer.js +382 -0
- package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
- package/lib/src/utils/addonDatabaseRules.js +57 -0
- package/lib/src/utils/addonHost.d.ts +51 -0
- package/lib/src/utils/addonHost.js +72 -0
- package/lib/src/utils/addonInstaller.d.ts +109 -0
- package/lib/src/utils/addonLock.d.ts +37 -0
- package/lib/src/utils/addonLock.js +48 -0
- package/lib/src/utils/addonPageSync.d.ts +45 -0
- package/lib/src/utils/addonProvenance.d.ts +48 -0
- package/lib/src/utils/addonTarball.d.ts +41 -0
- package/lib/src/utils/addonsPathResolver.d.ts +76 -0
- package/lib/src/utils/addonsPathResolver.js +129 -0
- package/lib/src/utils/assetMetadataTags.d.ts +66 -0
- package/lib/src/utils/atomicWrite.d.ts +28 -0
- package/lib/src/utils/auditConfigChange.d.ts +57 -0
- package/lib/src/utils/auditEventNames.d.ts +50 -0
- package/lib/src/utils/auditEventNames.generated.d.ts +169 -0
- package/lib/src/utils/auditEventNames.generated.js +174 -0
- package/lib/src/utils/auditEventNames.js +49 -0
- package/lib/src/utils/auditEvents.d.ts +265 -0
- package/lib/src/utils/auditEvents.js +309 -0
- package/lib/src/utils/auditRegistry.d.ts +102 -0
- package/lib/src/utils/auditRegistry.js +168 -0
- package/lib/src/utils/bip39English.d.ts +2 -0
- package/lib/src/utils/configEnvKeys.d.ts +68 -0
- package/lib/src/utils/configFiles.d.ts +74 -0
- package/lib/src/utils/configFiles.js +150 -0
- package/lib/src/utils/delegation.d.ts +48 -0
- package/lib/src/utils/deriveUsername.d.ts +21 -0
- package/lib/src/utils/explainMediaPath.d.ts +123 -0
- package/lib/src/utils/formerTitles.d.ts +69 -0
- package/lib/src/utils/frontmatterAccess.d.ts +54 -0
- package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
- package/lib/src/utils/imageTransform.d.ts +52 -0
- package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
- package/lib/src/utils/jobSlots.d.ts +43 -0
- package/lib/src/utils/keywordNormalizer.d.ts +127 -0
- package/lib/src/utils/logger.d.ts +70 -0
- package/lib/src/utils/logger.js +106 -0
- package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
- package/lib/src/utils/managerUtils.d.ts +40 -0
- package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
- package/lib/src/utils/orgFilename.d.ts +22 -0
- package/lib/src/utils/pageFeature.d.ts +27 -0
- package/lib/src/utils/pageFrontmatter.d.ts +21 -0
- package/lib/src/utils/pageNotes.d.ts +150 -0
- package/lib/src/utils/pageTitleRule.d.ts +37 -0
- package/lib/src/utils/pageToArticle.d.ts +59 -0
- package/lib/src/utils/pageUrl.d.ts +18 -0
- package/lib/src/utils/passwordChange.d.ts +12 -0
- package/lib/src/utils/passwordHash.d.ts +60 -0
- package/lib/src/utils/permissionCatalog.d.ts +52 -0
- package/lib/src/utils/pluginFormatters.d.ts +452 -0
- package/lib/src/utils/pluginFormatters.js +714 -0
- package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
- package/lib/src/utils/privateStoreAccess.d.ts +57 -0
- package/lib/src/utils/privateStoreAccess.js +65 -0
- package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
- package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
- package/lib/src/utils/privateStoreDoor.d.ts +181 -0
- package/lib/src/utils/privateStoreExport.d.ts +72 -0
- package/lib/src/utils/privateStoreFiles.d.ts +120 -0
- package/lib/src/utils/privateStoreMeta.d.ts +64 -0
- package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
- package/lib/src/utils/privateStorePath.d.ts +259 -0
- package/lib/src/utils/privateStorePath.js +436 -0
- package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
- package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
- package/lib/src/utils/proxyClaim.d.ts +59 -0
- package/lib/src/utils/proxyClaim.js +30 -0
- package/lib/src/utils/redactPrivateNames.d.ts +21 -0
- package/lib/src/utils/redactPrivateNames.js +89 -0
- package/lib/src/utils/redactSecrets.d.ts +58 -0
- package/lib/src/utils/redactSecrets.js +171 -0
- package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
- package/lib/src/utils/roleGrants.d.ts +35 -0
- package/lib/src/utils/safeRedirect.d.ts +32 -0
- package/lib/src/utils/schedule.d.ts +54 -0
- package/lib/src/utils/secretFileMode.d.ts +17 -0
- package/lib/src/utils/seededShippedPages.d.ts +45 -0
- package/lib/src/utils/sensitiveValues.d.ts +59 -0
- package/lib/src/utils/sensitiveValues.js +106 -0
- package/lib/src/utils/sessionEnd.d.ts +12 -0
- package/lib/src/utils/sessionGeneration.d.ts +24 -0
- package/lib/src/utils/sessionIdle.d.ts +41 -0
- package/lib/src/utils/sessionLimits.d.ts +68 -0
- package/lib/src/utils/shareLockbox.d.ts +64 -0
- package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
- package/lib/src/utils/sniffMime.d.ts +21 -0
- package/lib/src/utils/storeSearchIndex.d.ts +75 -0
- package/lib/src/utils/subjectMayDo.d.ts +21 -0
- package/lib/src/utils/systemCategoryRules.d.ts +30 -0
- package/lib/src/utils/systemCategoryRules.js +41 -0
- package/lib/src/utils/userCreateError.d.ts +62 -0
- package/lib/src/utils/username.d.ts +53 -0
- package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
- package/lib/src/utils/version.d.ts +84 -0
- package/lib/src/utils/videoFrame.d.ts +21 -0
- package/package.json +54 -3
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { ActorContext } from '../context/ActorContext.js';
|
|
2
|
+
import BaseManager from './BaseManager.js';
|
|
3
|
+
import type { WikiEngine } from '../types/WikiEngine.js';
|
|
4
|
+
/**
|
|
5
|
+
* Export file metadata interface
|
|
6
|
+
*/
|
|
7
|
+
export interface ExportFileInfo {
|
|
8
|
+
filename: string;
|
|
9
|
+
path: string;
|
|
10
|
+
size: number;
|
|
11
|
+
created: Date;
|
|
12
|
+
modified: Date;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Export configuration interface
|
|
16
|
+
*/
|
|
17
|
+
export interface ExportConfig extends Record<string, unknown> {
|
|
18
|
+
exportDirectory?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* User preferences interface (for locale support)
|
|
22
|
+
*/
|
|
23
|
+
export interface UserPreferences {
|
|
24
|
+
locale?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* User object interface (for locale-aware formatting)
|
|
28
|
+
*/
|
|
29
|
+
export interface ExportUser {
|
|
30
|
+
preferences?: UserPreferences;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Page object interface (minimal fields needed for export)
|
|
34
|
+
*/
|
|
35
|
+
export interface PageForExport {
|
|
36
|
+
content: string;
|
|
37
|
+
lastModified?: string;
|
|
38
|
+
'system-category'?: string;
|
|
39
|
+
'user-keywords'?: string[];
|
|
40
|
+
name?: string;
|
|
41
|
+
}
|
|
42
|
+
declare class ExportManager extends BaseManager {
|
|
43
|
+
private exportDirectory;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new ExportManager instance
|
|
46
|
+
*
|
|
47
|
+
* @constructor
|
|
48
|
+
* @param {any} engine - The wiki engine instance
|
|
49
|
+
*/
|
|
50
|
+
constructor(engine: WikiEngine);
|
|
51
|
+
/**
|
|
52
|
+
* One field of the one CSV writer for every export (RFC 4180): quoted when
|
|
53
|
+
* it holds a comma, quote or line break.
|
|
54
|
+
*
|
|
55
|
+
* A cell that starts with `=`, `+`, `-`, `@`, a tab or a carriage return is
|
|
56
|
+
* run as a formula by Excel, LibreOffice and Google Sheets ("CSV injection",
|
|
57
|
+
* OWASP), so a text cell starting with one gets a leading `'`. Numbers are
|
|
58
|
+
* written as numbers: a negative amount stays `-12550`.
|
|
59
|
+
*
|
|
60
|
+
* @param value - The cell value
|
|
61
|
+
* @returns The field, ready to join with commas
|
|
62
|
+
*/
|
|
63
|
+
csvCell(value: unknown): string;
|
|
64
|
+
/**
|
|
65
|
+
* A header row and data rows as one CSV document, each line ending CRLF.
|
|
66
|
+
* Every CSV export (the audit log, add-ons) goes through here.
|
|
67
|
+
*
|
|
68
|
+
* @param headers - The header row
|
|
69
|
+
* @param rows - The data rows
|
|
70
|
+
* @returns The CSV document
|
|
71
|
+
*/
|
|
72
|
+
toCsv(headers: readonly string[], rows: readonly (readonly unknown[])[]): string;
|
|
73
|
+
/**
|
|
74
|
+
* Initialize the ExportManager
|
|
75
|
+
*
|
|
76
|
+
* @async
|
|
77
|
+
* @param {ExportConfig} [config={}] - Configuration object
|
|
78
|
+
* @param {string} [config.exportDirectory] - Export directory path
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
initialize(config?: ExportConfig): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Export a single page to HTML
|
|
84
|
+
* @param {string} pageName - Page name to export
|
|
85
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
86
|
+
* @returns {Promise<string>} HTML content
|
|
87
|
+
*/
|
|
88
|
+
exportPageToHtml(pageName: string, ctx: ActorContext, user?: ExportUser | null): Promise<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Export multiple pages to a single HTML file
|
|
91
|
+
* @param {string[]} pageNames - Array of page names
|
|
92
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
93
|
+
* @returns {Promise<string>} Combined HTML content
|
|
94
|
+
*/
|
|
95
|
+
exportPagesToHtml(pageNames: string[], ctx: ActorContext, user?: ExportUser | null): Promise<string>;
|
|
96
|
+
/**
|
|
97
|
+
* Export page(s) to markdown
|
|
98
|
+
* @param {string|string[]} pageNames - Single page name or array of page names
|
|
99
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
100
|
+
* @returns {Promise<string>} Markdown content
|
|
101
|
+
*/
|
|
102
|
+
exportToMarkdown(pageNames: string | string[], ctx: ActorContext, user?: ExportUser | null): Promise<string>;
|
|
103
|
+
/**
|
|
104
|
+
* Save export to file
|
|
105
|
+
* @param {string} content - Content to save
|
|
106
|
+
* @param {string} filename - Filename
|
|
107
|
+
* @param {string} format - File format
|
|
108
|
+
* @returns {Promise<string>} File path
|
|
109
|
+
*/
|
|
110
|
+
saveExport(content: string, filename: string, format: string): Promise<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Get list of available exports
|
|
113
|
+
* @returns {Promise<ExportFileInfo[]>} List of export files
|
|
114
|
+
*/
|
|
115
|
+
getExports(): Promise<ExportFileInfo[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Delete an export file
|
|
118
|
+
* @param {string} filename - Export filename
|
|
119
|
+
* @returns {Promise<void>}
|
|
120
|
+
*/
|
|
121
|
+
deleteExport(filename: string): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Get formatted timestamp using user's locale
|
|
124
|
+
* @param {ExportUser|null} user - User object (optional)
|
|
125
|
+
* @returns {string} Formatted timestamp
|
|
126
|
+
*/
|
|
127
|
+
getFormattedTimestamp(user?: ExportUser | null): string;
|
|
128
|
+
}
|
|
129
|
+
export default ExportManager;
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import BaseManager from './BaseManager.js';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import LocaleUtils from '../utils/LocaleUtils.js';
|
|
5
|
+
import logger from '../utils/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* ExportManager - Handles page exports to multiple formats
|
|
8
|
+
*
|
|
9
|
+
* Similar to JSPWiki's export functionality, provides page export capabilities
|
|
10
|
+
* to HTML, PDF, markdown, and other formats.
|
|
11
|
+
*
|
|
12
|
+
* @class ExportManager
|
|
13
|
+
* @extends BaseManager
|
|
14
|
+
*
|
|
15
|
+
* @property {string} exportDirectory - Directory for exported files
|
|
16
|
+
*
|
|
17
|
+
* @see {@link BaseManager} for base functionality
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const exportManager = engine.getManager('ExportManager');
|
|
21
|
+
* const html = await exportManager.exportPageToHtml('Main');
|
|
22
|
+
*/
|
|
23
|
+
/** A text cell starting with one of these runs as a spreadsheet formula. */
|
|
24
|
+
const CSV_FORMULA_START = /^[=+\-@\t\r]/;
|
|
25
|
+
class ExportManager extends BaseManager {
|
|
26
|
+
exportDirectory;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new ExportManager instance
|
|
29
|
+
*
|
|
30
|
+
* @constructor
|
|
31
|
+
* @param {any} engine - The wiki engine instance
|
|
32
|
+
*/
|
|
33
|
+
constructor(engine) {
|
|
34
|
+
super(engine);
|
|
35
|
+
this.exportDirectory = './exports';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One field of the one CSV writer for every export (RFC 4180): quoted when
|
|
39
|
+
* it holds a comma, quote or line break.
|
|
40
|
+
*
|
|
41
|
+
* A cell that starts with `=`, `+`, `-`, `@`, a tab or a carriage return is
|
|
42
|
+
* run as a formula by Excel, LibreOffice and Google Sheets ("CSV injection",
|
|
43
|
+
* OWASP), so a text cell starting with one gets a leading `'`. Numbers are
|
|
44
|
+
* written as numbers: a negative amount stays `-12550`.
|
|
45
|
+
*
|
|
46
|
+
* @param value - The cell value
|
|
47
|
+
* @returns The field, ready to join with commas
|
|
48
|
+
*/
|
|
49
|
+
csvCell(value) {
|
|
50
|
+
if (value === null || value === undefined)
|
|
51
|
+
return '';
|
|
52
|
+
if (typeof value === 'number' || typeof value === 'bigint' || typeof value === 'boolean')
|
|
53
|
+
return String(value);
|
|
54
|
+
let text = typeof value === 'string' ? value : JSON.stringify(value);
|
|
55
|
+
if (CSV_FORMULA_START.test(text))
|
|
56
|
+
text = `'${text}`;
|
|
57
|
+
return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A header row and data rows as one CSV document, each line ending CRLF.
|
|
61
|
+
* Every CSV export (the audit log, add-ons) goes through here.
|
|
62
|
+
*
|
|
63
|
+
* @param headers - The header row
|
|
64
|
+
* @param rows - The data rows
|
|
65
|
+
* @returns The CSV document
|
|
66
|
+
*/
|
|
67
|
+
toCsv(headers, rows) {
|
|
68
|
+
return [headers, ...rows].map((row) => row.map((cell) => this.csvCell(cell)).join(',')).join('\r\n') + '\r\n';
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Initialize the ExportManager
|
|
72
|
+
*
|
|
73
|
+
* @async
|
|
74
|
+
* @param {ExportConfig} [config={}] - Configuration object
|
|
75
|
+
* @param {string} [config.exportDirectory] - Export directory path
|
|
76
|
+
* @returns {Promise<void>}
|
|
77
|
+
*/
|
|
78
|
+
async initialize(config = {}) {
|
|
79
|
+
await super.initialize(config);
|
|
80
|
+
// #1687: exports are files people generate — runtime data, so they live in
|
|
81
|
+
// the instance data folder, never in the checkout (root-owned in the image).
|
|
82
|
+
this.exportDirectory = config.exportDirectory
|
|
83
|
+
|| this.engine.getManager('ConfigurationManager')?.getResolvedDataPath('ngdpbase.directories.exports', '${FAST_STORAGE}/exports')
|
|
84
|
+
|| './exports';
|
|
85
|
+
const preflight = this.preflightConfiguredPath('exportDirectory', this.exportDirectory);
|
|
86
|
+
if (!preflight.ok) {
|
|
87
|
+
this.exportDirectory = '';
|
|
88
|
+
logger.info('ExportManager initialized (degraded — exports disabled)');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Create exports directory
|
|
92
|
+
await fs.mkdir(this.exportDirectory, { recursive: true });
|
|
93
|
+
logger.info('ExportManager initialized');
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Export a single page to HTML
|
|
97
|
+
* @param {string} pageName - Page name to export
|
|
98
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
99
|
+
* @returns {Promise<string>} HTML content
|
|
100
|
+
*/
|
|
101
|
+
async exportPageToHtml(pageName, ctx, user = null) {
|
|
102
|
+
const pageManager = this.engine.getManager('PageManager');
|
|
103
|
+
const renderingManager = this.engine.getManager('RenderingManager');
|
|
104
|
+
if (!pageManager || !renderingManager) {
|
|
105
|
+
throw new Error('Required managers not available');
|
|
106
|
+
}
|
|
107
|
+
const page = (await pageManager.getPage(pageName, ctx));
|
|
108
|
+
if (!page) {
|
|
109
|
+
throw new Error(`Page '${pageName}' not found`);
|
|
110
|
+
}
|
|
111
|
+
// Render the page content (without user context for exports)
|
|
112
|
+
const renderedContent = await renderingManager.renderMarkdown(page.content, pageName, null);
|
|
113
|
+
// Create full HTML document
|
|
114
|
+
const html = `<!DOCTYPE html>
|
|
115
|
+
<html lang="en">
|
|
116
|
+
<head>
|
|
117
|
+
<meta charset="UTF-8">
|
|
118
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
119
|
+
<title>${pageName} - ngdpbase Export</title>
|
|
120
|
+
<style>
|
|
121
|
+
body {
|
|
122
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
123
|
+
max-width: 800px;
|
|
124
|
+
margin: 0 auto;
|
|
125
|
+
padding: 2rem;
|
|
126
|
+
line-height: 1.6;
|
|
127
|
+
}
|
|
128
|
+
h1, h2, h3, h4, h5, h6 {
|
|
129
|
+
color: #333;
|
|
130
|
+
margin-top: 2rem;
|
|
131
|
+
margin-bottom: 1rem;
|
|
132
|
+
}
|
|
133
|
+
pre {
|
|
134
|
+
background: #f8f9fa;
|
|
135
|
+
padding: 1rem;
|
|
136
|
+
border-radius: 4px;
|
|
137
|
+
overflow-x: auto;
|
|
138
|
+
}
|
|
139
|
+
code {
|
|
140
|
+
background: #f8f9fa;
|
|
141
|
+
padding: 0.2rem 0.4rem;
|
|
142
|
+
border-radius: 3px;
|
|
143
|
+
font-size: 0.9em;
|
|
144
|
+
}
|
|
145
|
+
blockquote {
|
|
146
|
+
border-left: 4px solid #ddd;
|
|
147
|
+
padding-left: 1rem;
|
|
148
|
+
margin-left: 0;
|
|
149
|
+
color: #666;
|
|
150
|
+
}
|
|
151
|
+
table {
|
|
152
|
+
width: 100%;
|
|
153
|
+
border-collapse: collapse;
|
|
154
|
+
margin: 1rem 0;
|
|
155
|
+
}
|
|
156
|
+
th, td {
|
|
157
|
+
border: 1px solid #ddd;
|
|
158
|
+
padding: 0.75rem;
|
|
159
|
+
text-align: left;
|
|
160
|
+
}
|
|
161
|
+
th {
|
|
162
|
+
background: #f8f9fa;
|
|
163
|
+
font-weight: 600;
|
|
164
|
+
}
|
|
165
|
+
.export-meta {
|
|
166
|
+
border-top: 1px solid #eee;
|
|
167
|
+
margin-top: 3rem;
|
|
168
|
+
padding-top: 1rem;
|
|
169
|
+
color: #666;
|
|
170
|
+
font-size: 0.9em;
|
|
171
|
+
}
|
|
172
|
+
</style>
|
|
173
|
+
</head>
|
|
174
|
+
<body>
|
|
175
|
+
<h1>${pageName}</h1>
|
|
176
|
+
${renderedContent}
|
|
177
|
+
|
|
178
|
+
<div class="export-meta">
|
|
179
|
+
<p>Exported from ngdpbase on ${this.getFormattedTimestamp(user)}</p>
|
|
180
|
+
<p>Last modified: ${page.lastModified || 'Unknown'}</p>
|
|
181
|
+
${page['system-category'] ? `<p>System Category: ${page['system-category']}</p>` : ''}
|
|
182
|
+
${page['user-keywords'] && page['user-keywords'].length > 0 ? `<p>User Keywords: ${page['user-keywords'].join(', ')}</p>` : ''}
|
|
183
|
+
</div>
|
|
184
|
+
</body>
|
|
185
|
+
</html>`;
|
|
186
|
+
return html;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Export multiple pages to a single HTML file
|
|
190
|
+
* @param {string[]} pageNames - Array of page names
|
|
191
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
192
|
+
* @returns {Promise<string>} Combined HTML content
|
|
193
|
+
*/
|
|
194
|
+
async exportPagesToHtml(pageNames, ctx, user = null) {
|
|
195
|
+
const pageManager = this.engine.getManager('PageManager');
|
|
196
|
+
const renderingManager = this.engine.getManager('RenderingManager');
|
|
197
|
+
if (!pageManager || !renderingManager) {
|
|
198
|
+
throw new Error('Required managers not available');
|
|
199
|
+
}
|
|
200
|
+
let combinedContent = '';
|
|
201
|
+
const validPages = [];
|
|
202
|
+
for (const pageName of pageNames) {
|
|
203
|
+
const page = (await pageManager.getPage(pageName, ctx));
|
|
204
|
+
if (page) {
|
|
205
|
+
const renderedContent = await renderingManager.renderMarkdown(page.content, pageName, null);
|
|
206
|
+
combinedContent += `
|
|
207
|
+
<div class="page-section" id="page-${pageName.replace(/[^a-zA-Z0-9]/g, '-')}">
|
|
208
|
+
<h1>${pageName}</h1>
|
|
209
|
+
${renderedContent}
|
|
210
|
+
<hr style="margin: 3rem 0; border: none; border-top: 1px solid #eee;">
|
|
211
|
+
</div>
|
|
212
|
+
`;
|
|
213
|
+
validPages.push({ name: pageName, ...page });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Create table of contents
|
|
217
|
+
const toc = validPages.map((page) => `<li><a href="#page-${page.name.replace(/[^a-zA-Z0-9]/g, '-')}">${page.name}</a></li>`).join('\n');
|
|
218
|
+
const html = `<!DOCTYPE html>
|
|
219
|
+
<html lang="en">
|
|
220
|
+
<head>
|
|
221
|
+
<meta charset="UTF-8">
|
|
222
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
223
|
+
<title>ngdpbase Export - ${validPages.length} Pages</title>
|
|
224
|
+
<style>
|
|
225
|
+
body {
|
|
226
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
227
|
+
max-width: 900px;
|
|
228
|
+
margin: 0 auto;
|
|
229
|
+
padding: 2rem;
|
|
230
|
+
line-height: 1.6;
|
|
231
|
+
}
|
|
232
|
+
.toc {
|
|
233
|
+
background: #f8f9fa;
|
|
234
|
+
padding: 2rem;
|
|
235
|
+
border-radius: 8px;
|
|
236
|
+
margin-bottom: 3rem;
|
|
237
|
+
}
|
|
238
|
+
.toc h2 {
|
|
239
|
+
margin-top: 0;
|
|
240
|
+
}
|
|
241
|
+
.toc ul {
|
|
242
|
+
columns: 2;
|
|
243
|
+
column-gap: 2rem;
|
|
244
|
+
}
|
|
245
|
+
.page-section {
|
|
246
|
+
margin-bottom: 4rem;
|
|
247
|
+
}
|
|
248
|
+
h1, h2, h3, h4, h5, h6 {
|
|
249
|
+
color: #333;
|
|
250
|
+
margin-top: 2rem;
|
|
251
|
+
margin-bottom: 1rem;
|
|
252
|
+
}
|
|
253
|
+
pre {
|
|
254
|
+
background: #f8f9fa;
|
|
255
|
+
padding: 1rem;
|
|
256
|
+
border-radius: 4px;
|
|
257
|
+
overflow-x: auto;
|
|
258
|
+
}
|
|
259
|
+
code {
|
|
260
|
+
background: #f8f9fa;
|
|
261
|
+
padding: 0.2rem 0.4rem;
|
|
262
|
+
border-radius: 3px;
|
|
263
|
+
font-size: 0.9em;
|
|
264
|
+
}
|
|
265
|
+
blockquote {
|
|
266
|
+
border-left: 4px solid #ddd;
|
|
267
|
+
padding-left: 1rem;
|
|
268
|
+
margin-left: 0;
|
|
269
|
+
color: #666;
|
|
270
|
+
}
|
|
271
|
+
table {
|
|
272
|
+
width: 100%;
|
|
273
|
+
border-collapse: collapse;
|
|
274
|
+
margin: 1rem 0;
|
|
275
|
+
}
|
|
276
|
+
th, td {
|
|
277
|
+
border: 1px solid #ddd;
|
|
278
|
+
padding: 0.75rem;
|
|
279
|
+
text-align: left;
|
|
280
|
+
}
|
|
281
|
+
th {
|
|
282
|
+
background: #f8f9fa;
|
|
283
|
+
font-weight: 600;
|
|
284
|
+
}
|
|
285
|
+
.export-meta {
|
|
286
|
+
border-top: 1px solid #eee;
|
|
287
|
+
margin-top: 3rem;
|
|
288
|
+
padding-top: 1rem;
|
|
289
|
+
color: #666;
|
|
290
|
+
font-size: 0.9em;
|
|
291
|
+
}
|
|
292
|
+
@media print {
|
|
293
|
+
.page-section {
|
|
294
|
+
break-inside: avoid;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
</style>
|
|
298
|
+
</head>
|
|
299
|
+
<body>
|
|
300
|
+
<div class="toc">
|
|
301
|
+
<h2>Table of Contents</h2>
|
|
302
|
+
<ul>
|
|
303
|
+
${toc}
|
|
304
|
+
</ul>
|
|
305
|
+
<p><strong>${validPages.length}</strong> pages exported on ${this.getFormattedTimestamp(user)}</p>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
${combinedContent}
|
|
309
|
+
|
|
310
|
+
<div class="export-meta">
|
|
311
|
+
<p>Exported from ngdpbase on ${this.getFormattedTimestamp(user)}</p>
|
|
312
|
+
<p>Total pages: ${validPages.length}</p>
|
|
313
|
+
</div>
|
|
314
|
+
</body>
|
|
315
|
+
</html>`;
|
|
316
|
+
return html;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Export page(s) to markdown
|
|
320
|
+
* @param {string|string[]} pageNames - Single page name or array of page names
|
|
321
|
+
* @param {ExportUser|null} user - User object for locale-aware formatting
|
|
322
|
+
* @returns {Promise<string>} Markdown content
|
|
323
|
+
*/
|
|
324
|
+
async exportToMarkdown(pageNames, ctx, user = null) {
|
|
325
|
+
const pageManager = this.engine.getManager('PageManager');
|
|
326
|
+
if (!pageManager) {
|
|
327
|
+
throw new Error('PageManager not available');
|
|
328
|
+
}
|
|
329
|
+
const names = Array.isArray(pageNames) ? pageNames : [pageNames];
|
|
330
|
+
let markdown = '';
|
|
331
|
+
if (names.length > 1) {
|
|
332
|
+
markdown += '# ngdpbase Export\n\n';
|
|
333
|
+
markdown += `*Exported on ${this.getFormattedTimestamp(user)}*\n\n`;
|
|
334
|
+
markdown += '## Table of Contents\n\n';
|
|
335
|
+
for (const pageName of names) {
|
|
336
|
+
markdown += `- [${pageName}](#${pageName.toLowerCase().replace(/[^a-z0-9]/g, '-')})\n`;
|
|
337
|
+
}
|
|
338
|
+
markdown += '\n---\n\n';
|
|
339
|
+
}
|
|
340
|
+
for (const pageName of names) {
|
|
341
|
+
const page = (await pageManager.getPage(pageName, ctx));
|
|
342
|
+
if (page) {
|
|
343
|
+
if (names.length > 1) {
|
|
344
|
+
markdown += `# ${pageName}\n\n`;
|
|
345
|
+
}
|
|
346
|
+
markdown += page.content;
|
|
347
|
+
if (names.length > 1) {
|
|
348
|
+
markdown += '\n\n---\n\n';
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return markdown;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Save export to file
|
|
356
|
+
* @param {string} content - Content to save
|
|
357
|
+
* @param {string} filename - Filename
|
|
358
|
+
* @param {string} format - File format
|
|
359
|
+
* @returns {Promise<string>} File path
|
|
360
|
+
*/
|
|
361
|
+
async saveExport(content, filename, format) {
|
|
362
|
+
const sanitizedFilename = filename.replace(/[^a-zA-Z0-9\-_]/g, '-');
|
|
363
|
+
const timestamp = new Date().toISOString().slice(0, 10);
|
|
364
|
+
const fullFilename = `${sanitizedFilename}_${timestamp}.${format}`;
|
|
365
|
+
const filePath = path.join(this.exportDirectory, fullFilename);
|
|
366
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
367
|
+
logger.info(`Exported to: ${fullFilename}`);
|
|
368
|
+
return filePath;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get list of available exports
|
|
372
|
+
* @returns {Promise<ExportFileInfo[]>} List of export files
|
|
373
|
+
*/
|
|
374
|
+
async getExports() {
|
|
375
|
+
try {
|
|
376
|
+
const files = await fs.readdir(this.exportDirectory);
|
|
377
|
+
const exports = [];
|
|
378
|
+
for (const file of files) {
|
|
379
|
+
const filePath = path.join(this.exportDirectory, file);
|
|
380
|
+
const stats = await fs.stat(filePath);
|
|
381
|
+
exports.push({
|
|
382
|
+
filename: file,
|
|
383
|
+
path: filePath,
|
|
384
|
+
size: stats.size,
|
|
385
|
+
created: stats.birthtime,
|
|
386
|
+
modified: stats.mtime
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
return exports.sort((a, b) => b.created.getTime() - a.created.getTime());
|
|
390
|
+
}
|
|
391
|
+
catch (err) {
|
|
392
|
+
logger.error('Error getting exports:', err);
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Delete an export file
|
|
398
|
+
* @param {string} filename - Export filename
|
|
399
|
+
* @returns {Promise<void>}
|
|
400
|
+
*/
|
|
401
|
+
async deleteExport(filename) {
|
|
402
|
+
const filePath = path.join(this.exportDirectory, filename);
|
|
403
|
+
await fs.unlink(filePath);
|
|
404
|
+
logger.info(`Deleted export: ${filename}`);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Get formatted timestamp using user's locale
|
|
408
|
+
* @param {ExportUser|null} user - User object (optional)
|
|
409
|
+
* @returns {string} Formatted timestamp
|
|
410
|
+
*/
|
|
411
|
+
getFormattedTimestamp(user = null) {
|
|
412
|
+
const date = new Date();
|
|
413
|
+
if (user && user.preferences && user.preferences.locale) {
|
|
414
|
+
return LocaleUtils.formatDate(date, user.preferences.locale) + ' ' + LocaleUtils.formatTime(date, user.preferences.locale);
|
|
415
|
+
}
|
|
416
|
+
// Fallback to system default
|
|
417
|
+
return date.toLocaleString();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
export default ExportManager;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import BaseManager from './BaseManager.js';
|
|
2
|
+
import type { WikiEngine } from '../types/WikiEngine.js';
|
|
3
|
+
import { type ActorContext } from '../context/ActorContext.js';
|
|
4
|
+
import { type VaultPageNotesOutside, type PageRef } from '../utils/pageNotes.js';
|
|
5
|
+
export interface PageFootnote {
|
|
6
|
+
id: string;
|
|
7
|
+
display: string;
|
|
8
|
+
url: string;
|
|
9
|
+
note: string;
|
|
10
|
+
createdBy: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
export default class FootnoteManager extends BaseManager {
|
|
14
|
+
private storageDir;
|
|
15
|
+
private enabled;
|
|
16
|
+
/** Vault pages whose footnotes are still in the public folder (#1839), and the repair's re-check (#1842). */
|
|
17
|
+
private readonly outsideCheck;
|
|
18
|
+
constructor(engine: WikiEngine);
|
|
19
|
+
initialize(): Promise<void>;
|
|
20
|
+
isEnabled(): boolean;
|
|
21
|
+
/** The public folder and the vaults, as configured now (#1839). */
|
|
22
|
+
private roots;
|
|
23
|
+
/**
|
|
24
|
+
* Where `page`'s footnotes are (#1839): the public folder for a public page,
|
|
25
|
+
* the page's own vault for a vault page, read and written through that
|
|
26
|
+
* vault's store I/O. A locked vault, or a sealed kind's vault not yet
|
|
27
|
+
* opened, throws: a vault page's footnotes are never read or written in
|
|
28
|
+
* the clear.
|
|
29
|
+
*/
|
|
30
|
+
private place;
|
|
31
|
+
private readMap;
|
|
32
|
+
private writeMap;
|
|
33
|
+
/**
|
|
34
|
+
* A page's footnotes, read as `ctx` may (#1839). Whether `ctx` may read the
|
|
35
|
+
* page is the caller's to decide, as for the page itself; this finds and
|
|
36
|
+
* opens them.
|
|
37
|
+
*/
|
|
38
|
+
getFootnotes(page: PageRef, ctx: ActorContext): Promise<PageFootnote[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Add a footnote on someone's behalf (#1233, security-posture P1).
|
|
41
|
+
*
|
|
42
|
+
* `ctx` is the request's subject — `wikiContext.userContext`, forwarded —
|
|
43
|
+
* or a JobContext for an import; never a name. `createdBy` is read from
|
|
44
|
+
* it, and the write is recorded as `footnote-edit` / `add`.
|
|
45
|
+
*/
|
|
46
|
+
addFootnote(page: PageRef, data: {
|
|
47
|
+
display: string;
|
|
48
|
+
url: string;
|
|
49
|
+
note: string;
|
|
50
|
+
}, ctx: ActorContext): Promise<PageFootnote>;
|
|
51
|
+
/**
|
|
52
|
+
* #1125: import a footnote with an EXPLICIT id — the NCM conversion path.
|
|
53
|
+
*
|
|
54
|
+
* Unlike {@link addFootnote}, which assigns the next sequential id, this
|
|
55
|
+
* preserves the author's id verbatim: the body's `[^note-1]` refs resolve
|
|
56
|
+
* to `#footnote-note-1` in the rendered list, so renumbering would break
|
|
57
|
+
* every ref. Refuses to clobber an existing id (returns false) — the
|
|
58
|
+
* caller surfaces that as a warning and leaves the body definition alone.
|
|
59
|
+
*/
|
|
60
|
+
importFootnote(page: PageRef, id: string, data: {
|
|
61
|
+
display: string;
|
|
62
|
+
url: string;
|
|
63
|
+
note: string;
|
|
64
|
+
}, ctx: ActorContext): Promise<boolean>;
|
|
65
|
+
/** The write behind `importFootnote` and `transferFromContent`; the callers record it, once each. */
|
|
66
|
+
private putImported;
|
|
67
|
+
/**
|
|
68
|
+
* #1125/#1126: transfer `[^id]: text` definitions from a body into this
|
|
69
|
+
* sidecar, returning the rewritten body. THE one implementation — the
|
|
70
|
+
* convert route, agent ingest, and ImportManager all delegate here, so the
|
|
71
|
+
* funnel cannot drift per-path. dryRun reports and rewrites without
|
|
72
|
+
* writing. A colliding id keeps its body definition and warns.
|
|
73
|
+
*/
|
|
74
|
+
transferFromContent(page: PageRef, content: string, ctx: ActorContext, dryRun: boolean): Promise<{
|
|
75
|
+
content: string;
|
|
76
|
+
warnings: string[];
|
|
77
|
+
}>;
|
|
78
|
+
updateFootnote(page: PageRef, id: string, data: {
|
|
79
|
+
display: string;
|
|
80
|
+
url: string;
|
|
81
|
+
note: string;
|
|
82
|
+
}, ctx: ActorContext): Promise<PageFootnote | null>;
|
|
83
|
+
deleteFootnote(page: PageRef, id: string, ctx: ActorContext): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* `footnote-edit`, attributed from the context (#1233). Ids only — display,
|
|
86
|
+
* url and note are content, and the record does not repeat content.
|
|
87
|
+
* on-failure: continue, the page-edit footing.
|
|
88
|
+
*/
|
|
89
|
+
private recordEdit;
|
|
90
|
+
hasFootnotes(page: PageRef, ctx: ActorContext): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Take a page's footnotes with it when it changes place (#1839): into a
|
|
93
|
+
* vault, out of one, or between two, through both sides' store I/O as its
|
|
94
|
+
* history goes, sealed into a sealed vault and opened coming out. The page
|
|
95
|
+
* door calls this after the page itself has moved; a rename in place moves
|
|
96
|
+
* nothing.
|
|
97
|
+
*/
|
|
98
|
+
movePageFootnotes(uuid: string, fromName: string, toName: string, ctx: ActorContext): Promise<boolean>;
|
|
99
|
+
/** Vault pages whose footnotes the last check found in the public folder (#1839): owner, vault, page uuid. */
|
|
100
|
+
vaultPageNotesOutside(): VaultPageNotesOutside[];
|
|
101
|
+
/** Run that check again (#1842): after a repair, so the subsystem banner clears once nothing is left. */
|
|
102
|
+
recheckVaultPageNotesOutside(): Promise<VaultPageNotesOutside[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Move vault page `uuid`'s footnotes left in the public folder into its
|
|
105
|
+
* vault (#1842), sealed when the vault is; merged with any the vault already
|
|
106
|
+
* has. Who may ask, and that `uuid` is a page of `vault`, is the caller's
|
|
107
|
+
* (`PageManager.repairVaultPage`) to decide.
|
|
108
|
+
*
|
|
109
|
+
* @returns how many footnotes were (or, with `dryRun`, would be) moved
|
|
110
|
+
*/
|
|
111
|
+
moveOutsideFootnotesIntoVault(vault: {
|
|
112
|
+
owner: string;
|
|
113
|
+
store: string;
|
|
114
|
+
}, uuid: string, ctx: ActorContext, opts?: {
|
|
115
|
+
dryRun?: boolean;
|
|
116
|
+
}): Promise<number>;
|
|
117
|
+
shutdown(): Promise<void>;
|
|
118
|
+
}
|