Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tmrodrig committed Aug 11, 2022
0 parents commit 2a3c7ab
Show file tree
Hide file tree
Showing 9 changed files with 954 additions and 0 deletions.
47 changes: 47 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Dependency directories
node_modules/
jspm_packages/

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Visual Studio
.vscode/
*.code-workspace

# macOS specific files
# general
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Build files
build/

# Distrubution files
dist/

# Package builds
package/

# Hidden files
nogit/

# Foundry Project Creator config file
foundryconfig.json
360 changes: 360 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Split Join Journal
[![Version (latest)](https://img.shields.io/github/v/release/toastygm/split-join-journal)](https://github.com/toastygm/split-join-journal/releases/latest)
[![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Fsplit-join-journal&colorB=4aa94a)](https://forge-vtt.com/bazaar#package=split-join-journal)
[![GitHub downloads (latest)](https://img.shields.io/badge/dynamic/json?label=Downloads@latest&query=assets[?(@.name.includes('zip'))].download_count&url=https://api.github.com/repos/toastygm/split-join-journal/releases/latest&color=green)](https://github.com/toastygm/split-join-journal/releases/latest)


Foundry VTT v10 introduced the new Journals V2. This module lets you manage pages and Journals, merging and organizing them simply.

With this module you can:
1. Split a single Journal Page based on HTML headings into separate pages, either in the same Journal or in a separate Journal.
2. Split all of the pages in a Journal into separate Journals (one page per journal), either in a new folder or in the existing folder.
3. Join all of the Journals (and all of their pages) within a single folder into a new single Journal, with all of the pages from all of the Journals.

27 changes: 27 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"SPLITJOINJNL.SPLITPAGE.title": "Split Journal Page",
"SPLITJOINJNL.SPLITPAGE.splitSubmit": "Split Journal Page",
"SPLITJOINJNL.SPLITPAGE.contextMenu": "Split Journal Page",
"SPLITJOINJNL.SPLITPAGE.description": "Split the journal page '{name}' into multiple pages.",
"SPLITJOINJNL.SPLITPAGE.splitOn": "Split on",
"SPLITJOINJNL.SPLITPAGE.journalNameDesc": "Provide a new journal name, or blank to split into existing journal.",
"SPLITJOINJNL.SPLITPAGE.journalName": "Journal Name",
"SPLITJOINJNL.SPLITPAGE.errorNoHeadings": "Journal {journalName} page {pageName} does not have any headings, cannot split.",
"SPLITJOINJNL.SPLITPAGE.errorNotText": "Journal {journalName} page {pageName} does not have text, cannot split.",
"SPLITJOINJNL.SPLITPAGE.errorJournalPageEmpty": "This Journal page is empty. There is nothing to split.",
"SPLITJOINJNL.SPLITJOURNAL.title": "Split Journal",
"SPLITJOINJNL.SPLITJOURNAL.splitSubmit": "Split Journal",
"SPLITJOINJNL.SPLITJOURNAL.contextMenu": "Split Journal",
"SPLITJOINJNL.SPLITJOURNAL.description": "Split Journal",
"SPLITJOINJNL.SPLITJOURNAL.folderNameDesc": "Provide a new folder name, or blank to split into existing folder.",
"SPLITJOINJNL.SPLITJOURNAL.folderName": "Folder Name",
"SPLITJOINJNL.MERGEFOLDER.title": "Join Journal Pages",
"SPLITJOINJNL.MERGEFOLDER.contextMenu": "Join Journal Pages",
"SPLITJOINJNL.HEADING1": "Heading 1",
"SPLITJOINJNL.HEADING2": "Heading 2",
"SPLITJOINJNL.HEADING3": "Heading 3",
"SPLITJOINJNL.HEADING4": "Heading 4",
"SPLITJOINJNL.HEADING5": "Heading 5",
"SPLITJOINJNL.HEADING6": "Heading 6",
"SPLITJOINJNL.HEADING7": "Heading 7"
}
43 changes: 43 additions & 0 deletions module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"id": "split-join-journal",
"title": "Split-Join Journal",
"description": "Split and Join pages within a Journal or Journals within a folder.",
"version": "1.0.0",
"url": "https://github.com/toastygm/split-join-journal",
"bugs": "https://github.com/toastygm/split-join-journal/issues",
"license": "LICENSE",
"readme": "README.md",
"authors": [
{
"name": "Toasty",
"discord": "toasty#8538",
"flags": {}
}
],
"flags": {
"allowBugReporter": true
},
"compatibility": {
"minimum": "10",
"verified": "10"
},
"scripts": [
"scripts/split-html.js",
"scripts/split-join-journal.js"
],
"esmodules": [],
"styles": [],
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"packs": [],
"system": [],
"dependencies": [],
"socket": true,
"manifest": "https://github.com/toastygm/split-join-journal/releases/latest/download/module.json",
"download": "https://github.com/toastygm/split-join-journal/releases/download/v1.1.2/module.zip"
}
150 changes: 150 additions & 0 deletions scripts/split-html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// This code comes from
// https://github.com/apostrophecms/split-html
// Copyright (c) 2016 P'unk Avenue LLC

(function() {
var cheerio;
if (typeof window === 'undefined') {
// node
module.exports = splitHtml;
cheerio = require('cheerio');
} else {
window.splitHtml = splitHtml;
// In the browser, use actual jQuery in place of Cheerio.
// Create a simulated cheerio object.
cheerio = {
load: function(html) {
var $wrapper = jQuery('<div data-cheerio-root>');
var $el = jQuery(html);
$wrapper.append($el);
function c(s) {
if (s[0] === '<') {
return jQuery(s);
}
return $wrapper.find(s);
}
c.html = function() {
return $wrapper.html();
};
return c;
},
};
}
function splitHtml(html, splitOn, test) {
if (!test) {
test = function($el) {
return true;
};
}
var result = [];
var splitAttr = 'data-' + token();
var ignoreAttr = 'data-' + token();
var $;
var $matches;
var i;
var $match;
var $wrapper;
var tag;
var second;
while (true) {
$ = cheerio.load(html);
$matches = $(splitOn);
$match = null;
for (i = 0; (i < $matches.length); i++) {
$match = $matches.eq(i);
if ((!$match.attr(ignoreAttr)) && test($match)) {
break;
} else {
$match.attr(ignoreAttr, '1');
}
$match = null;
}
if (!$match) {
result.push(html);
break;
}
$match.attr(splitAttr, '1');
var markup = $.html();
var splitAt = markup.indexOf(splitAttr);
var leftAt = markup.lastIndexOf('<', splitAt);
if (leftAt === -1) {
result.push(html);
break;
}
var first = markup.substr(0, leftAt);

// For the second segment we need to reopen the
// open tags from the first segment. Reconstruct that.

var reopen = '';
$wrapper = cheerio.load('<div></div>')('div').eq(0);
var $parents = $match.parents();
for (i = 0; (i < $parents.length); i++) {
var $original = $parents.eq(i);
if ($original.is('[data-cheerio-root]')) {
// Simulated cheerio used in browser has
// a wrapper element
break;
}
var $parent = $original.clone();
$parent.empty();
$wrapper.empty();
$wrapper.append($parent);
var parentMarkup = $wrapper.html();
var endTagAt = parentMarkup.indexOf('>');
tag = tagName($parent);
// Cheerio tolerates missing closing tags,
// but real jQuery will discard any text
// preceding them, so play nice
first += '</' + tag + '>';
reopen = parentMarkup.substr(0, endTagAt + 1) + reopen;
}

// We can't just split off the next fragment at
// > because the matching tag may be a container.
// Move it to a wrapper to get its full markup,
// then remove it from the original document. The
// remainder of the original document now begins
// where the matching tag used to

markup = $.html();

$wrapper = cheerio.load('<div></div>')('div').eq(0);
$match.removeAttr(splitAttr);
$wrapper.append($match);
tag = $wrapper.html();
$match.remove();
markup = $.html();
second = reopen + markup.substr(leftAt);
// Let Cheerio close the open tags in the
// first segment for us. Also mop up the attributes
// we used to mark elements that matched the selector
// but didn't match our test function
first = cleanup(first);
result.push(first);
result.push(tag);
html = cleanup(second);
}
return result;
// Use Cheerio to strip out any attributes we used to keep
// track of our work, then generate new HTML. This also
// closes any tags we opened but did not close.
function cleanup(html) {
html = cheerio.load(html);
html('[' + ignoreAttr + ']').removeAttr(ignoreAttr);
html = html.html();
return html;
}

function token() {
return Math.floor(Math.random() * 1000000000).toString();
}
}

function tagName($el) {
// Different in DOM and Cheerio. Cheerio
// doesn't support prop() either.
return $el[0].tagName || $el[0].name;
}
})();

Loading

0 comments on commit 2a3c7ab

Please sign in to comment.