diff --git a/README.md b/README.md index 262b034..494219e 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,20 @@ A module for Foundry VTT that links entities (journal entries, actors and items) This module adds wiki-style "referenced by" links to journals, actors and items, allowing easy browsing. It doesn't change the actual text of the journal/bio/etc, but displays it as though it was part of the entry! +![a variety of entities showing links](example.png) + ## Installing Add the manifest to your Foundry modules: https://raw.githubusercontent.com/Sigafoos/journal-links/master/module.json (automatic discovery/install in Foundry itself coming soon) +## Linking entities +In general the linking should happen automatically: this module detects that it hasn't ever run and will run an initial sync. Whenever you save an entity (journal entry, actor bio, item description) it will detect all entities linked in the text and link them if the "Rebuild on save" setting is enabled (there shouldn't be a reason to disable it, as I don't anticipate performance issues, but it's included just in case). + +If you've disabled "Rebuild on save" (or just feel like it), in the module settings you can click the 'Sync now' button to perform a sync. + +The module may perform additional automatic syncs after an update which fixes a bug, etc. + ## Settings * **Rebuild on save**: if disabled, won't automatically generate links between entities (default: enabled) * **Heading tag**: by default it uses `

` tags for the section. If you'd like to change it to `

`, etc, you can (note: this doesn't support custom classes, attributes, etc) diff --git a/example.png b/example.png new file mode 100644 index 0000000..19b7e65 Binary files /dev/null and b/example.png differ diff --git a/module.json b/module.json index dd80806..b2aef6c 100644 --- a/module.json +++ b/module.json @@ -2,7 +2,7 @@ "name": "journal-links", "title": "Journal Links", "description": "Include links to entities that reference the viewed journal, actor, item, etc.", - "version": "0.2.0", + "version": "0.3.0", "author": "dconley", "esmodules": ["./scripts/index.js"], "scripts": [], diff --git a/scripts/index.js b/scripts/index.js index cbef5af..9787fc5 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,5 +1,8 @@ import { JournalLink } from './journallink.js'; -//import { JournalLinkSettings } from './settings.js'; +import { Sync } from './sync.js'; + +// bump this to cause a sync on page load (one time) +const SYNC_VERSION = 1; const MODULE_NAME = 'journal-links'; const NAME = 'Journal Links'; @@ -25,18 +28,31 @@ Hooks.on("init", () => { }); game.settings.register(MODULE_NAME, 'debug', { name : 'Debug logging', - scope: 'world', - config: 'client', + scope: 'client', + config: true, type: Boolean, default: false }); + game.settings.register(MODULE_NAME, 'lastSyncedVersion', { + name : 'Last synced version', + hint: 'If we perform a bugfix that would benefit from resyncing, SYNC_VERSION will be out of -- forgive me -- sync, indicating we should perform a sync', + scope: 'world', + config: false, + type: Number, + default: 0 + }); + game.settings.registerMenu(MODULE_NAME, 'syncButton', { + name: 'Sync entries', + label: 'Sync now', + icon: 'fas fa-sync-alt', + type: Sync, + restricted: true + }); let jl = new JournalLink(); game.JournalLink = jl; CONFIG.debug.JournalLinks = game.settings.get(MODULE_NAME, 'debug'); - // roll tables have no context of this stuff - // things what update Hooks.on('updateJournalEntry', game.JournalLink.updateJournalEntry.bind(jl)); Hooks.on('updateActor', game.JournalLink.updateActor.bind(jl)); @@ -46,4 +62,13 @@ Hooks.on("init", () => { Hooks.on('renderJournalSheet', game.JournalLink.includeJournalLinks.bind(jl)); Hooks.on('renderActorSheet', game.JournalLink.includeActorLinks.bind(jl)); Hooks.on('renderItemSheet', game.JournalLink.includeItemLinks.bind(jl)); + + // initial sync + Hooks.on('ready', () => { + if (game.settings.get(MODULE_NAME, 'lastSyncedVersion') < SYNC_VERSION) { + console.log('journal-links | performing sync...'); + game.JournalLink.sync(); + game.settings.set(MODULE_NAME, 'lastSyncedVersion', SYNC_VERSION); + } + }); }); diff --git a/scripts/journallink.js b/scripts/journallink.js index 9b65241..20d0f3d 100644 --- a/scripts/journallink.js +++ b/scripts/journallink.js @@ -14,23 +14,31 @@ export class JournalLink { ]; updateJournalEntry({ data }) { + if (!game.settings.get('journal-links', 'rebuildOnSave')) { + this.log('not updating ' + entityType + ' ' + data.name + ' as rebuildOnSave is false'); + return; + } this.update(data, 'JournalEntry', data.content); } updateActor({ data }) { + if (!game.settings.get('journal-links', 'rebuildOnSave')) { + this.log('not updating ' + entityType + ' ' + data.name + ' as rebuildOnSave is false'); + return; + } this.update(data, 'Actor', data.data.details.biography.value); } updateItem({ data }) { + if (!game.settings.get('journal-links', 'rebuildOnSave')) { + this.log('not updating ' + entityType + ' ' + data.name + ' as rebuildOnSave is false'); + return; + } this.update(data, 'Item', data.data.description.value); } // TODO is the lack of async/await here going to bite me? update(data, entityType, content) { - if (!game.settings.get('journal-links', 'rebuildOnSave')) { - this.log('not updating ' + entityType + ' ' + data.name + ' as rebuildOnSave is false'); - return; - } this.log('updating ' + entityType + ' ' + data.name); let references = this.references(content); diff --git a/scripts/sync.js b/scripts/sync.js new file mode 100644 index 0000000..73b72c3 --- /dev/null +++ b/scripts/sync.js @@ -0,0 +1,21 @@ +// this is handled as a setting menu but only uses that as a hack to do its work +export class Sync extends FormApplication { + constructor(object = {}, options) { + super(object, options); + + // no idea how this would happen, but CYA + if (!game.JournalLink) { + ui.notifications.warn('JournalLink object not found; cannot sync') + } else { + ui.notifications.info('Syncing journal links'); + game.JournalLink.sync(); + ui.notifications.info('Journal link sync completed'); + } + + // there shouldn't be anything to close, but just in case! + this.close(); + } + + // not overriding this causes it to try to actually render, throwing an error + render = () => {}; +}