mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-27 13:23:42 +00:00
Compare commits
13 Commits
browser-me
...
docs-make-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1a8b56124 | ||
|
|
88b472c955 | ||
|
|
8c956a9448 | ||
|
|
4bb0bc5527 | ||
|
|
3378497816 | ||
|
|
d81204c6ab | ||
|
|
e001c21bf5 | ||
|
|
102c236267 | ||
|
|
06a2923adf | ||
|
|
54e5ef7489 | ||
|
|
6f306d1ed6 | ||
|
|
5dfdbc8ea0 | ||
|
|
4d4d9d9995 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
|
||||
TW5_BUILD_OUTPUT: "./output/prerelease"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
TW5_BUILD_OUTPUT: "./output"
|
||||
TW5_BUILD_ARCHIVE: "./output"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
|
||||
40
.github/workflows/eslint.yml
vendored
40
.github/workflows/eslint.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: ESLint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: lint-${{ github.event.pull_request.number || github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# Needed for GitHub Checks API
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --include=dev
|
||||
|
||||
- name: Run ESLint with reviewdog (GitHub Checks)
|
||||
uses: reviewdog/action-eslint@v1
|
||||
with:
|
||||
eslint_flags: '.'
|
||||
reporter: github-pr-check
|
||||
fail_level: error
|
||||
level: error
|
||||
tool_name: ESLint PR code
|
||||
@@ -5,7 +5,7 @@
|
||||
# Default to the current version number for building the plugin library
|
||||
|
||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||
TW5_BUILD_VERSION=v5.4.0
|
||||
TW5_BUILD_VERSION=v5.3.8
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||
@@ -73,8 +73,10 @@ rm $TW5_BUILD_OUTPUT/dev/static/*
|
||||
|
||||
echo "<a href='./plugins/tiddlywiki/tw2parser/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tw2parser/index.html</a>" > $TW5_BUILD_OUTPUT/classicparserdemo.html
|
||||
echo "<a href='./plugins/tiddlywiki/codemirror/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/codemirror/index.html</a>" > $TW5_BUILD_OUTPUT/codemirrordemo.html
|
||||
echo "<a href='./plugins/tiddlywiki/d3/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/d3/index.html</a>" > $TW5_BUILD_OUTPUT/d3demo.html
|
||||
echo "<a href='./plugins/tiddlywiki/highlight/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/highlight/index.html</a>" > $TW5_BUILD_OUTPUT/highlightdemo.html
|
||||
echo "<a href='./plugins/tiddlywiki/markdown/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/markdown/index.html</a>" > $TW5_BUILD_OUTPUT/markdowndemo.html
|
||||
echo "<a href='./plugins/tiddlywiki/tahoelafs/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tahoelafs/index.html</a>" > $TW5_BUILD_OUTPUT/tahoelafs.html
|
||||
|
||||
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
|
||||
|
||||
@@ -299,6 +301,26 @@ node $TW5_BUILD_TIDDLYWIKI \
|
||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# /plugins/tiddlywiki/tahoelafs/index.html Demo wiki with Tahoe-LAFS plugin
|
||||
# /plugins/tiddlywiki/tahoelafs/empty.html Empty wiki with Tahoe-LAFS plugin
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
./editions/tahoelafs \
|
||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
||||
--output $TW5_BUILD_OUTPUT \
|
||||
--rendertiddler $:/core/save/all plugins/tiddlywiki/tahoelafs/index.html text/plain \
|
||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tahoelafs/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# /plugins/tiddlywiki/d3/index.html Demo wiki with D3 plugin
|
||||
# /plugins/tiddlywiki/d3/empty.html Empty wiki with D3 plugin
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
./editions/d3demo \
|
||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
||||
--output $TW5_BUILD_OUTPUT \
|
||||
--rendertiddler $:/core/save/all plugins/tiddlywiki/d3/index.html text/plain \
|
||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/d3/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
|
||||
# /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
|
||||
69
boot/boot.js
69
boot/boot.js
@@ -641,7 +641,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
||||
// Call the function and return the exports
|
||||
return fn.apply(null,contextValues);
|
||||
};
|
||||
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
|
||||
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
|
||||
/*
|
||||
Run code in a sandbox with only the specified context variables in scope
|
||||
*/
|
||||
@@ -799,13 +799,12 @@ the password, and to encrypt/decrypt a block of text
|
||||
$tw.utils.Crypto = function() {
|
||||
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
|
||||
currentPassword = null,
|
||||
callSjcl = function(method,inputText,password,options) {
|
||||
options = options || {};
|
||||
callSjcl = function(method,inputText,password) {
|
||||
password = password || currentPassword;
|
||||
var outputText;
|
||||
try {
|
||||
if(password) {
|
||||
outputText = sjcl[method](password,inputText,options);
|
||||
outputText = sjcl[method](password,inputText);
|
||||
}
|
||||
} catch(ex) {
|
||||
console.log("Crypto error:" + ex);
|
||||
@@ -831,8 +830,7 @@ $tw.utils.Crypto = function() {
|
||||
return !!currentPassword;
|
||||
}
|
||||
this.encrypt = function(text,password) {
|
||||
// set default ks:256 -- see: http://bitwiseshiftleft.github.io/sjcl/doc/convenience.js.html
|
||||
return callSjcl("encrypt",text,password,{v:1,iter:10000,ks:256,ts:64,mode:"ccm",adata:"",cipher:"aes"});
|
||||
return callSjcl("encrypt",text,password);
|
||||
};
|
||||
this.decrypt = function(text,password) {
|
||||
return callSjcl("decrypt",text,password);
|
||||
@@ -1435,7 +1433,7 @@ $tw.Wiki = function(options) {
|
||||
checkTiddler = function(tiddler,title) {
|
||||
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
|
||||
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
||||
if(title === "$:/core" || title === "$:/core-server" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
||||
pluginTiddlers.push(tiddler);
|
||||
registeredTitles.push(tiddler.fields.title);
|
||||
@@ -1532,8 +1530,7 @@ Define all modules stored in ordinary tiddlers
|
||||
*/
|
||||
$tw.Wiki.prototype.defineTiddlerModules = function() {
|
||||
this.each(function(tiddler,title) {
|
||||
// Modules in draft tiddlers are disabled
|
||||
if(tiddler.hasField("module-type") && (!tiddler.hasField("draft.of"))) {
|
||||
if(tiddler.hasField("module-type")) {
|
||||
switch(tiddler.fields.type) {
|
||||
case "application/javascript":
|
||||
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
|
||||
@@ -1560,11 +1557,6 @@ $tw.Wiki.prototype.defineShadowModules = function() {
|
||||
this.eachShadow(function(tiddler,title) {
|
||||
// Don't define the module if it is overidden by an ordinary tiddler
|
||||
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
|
||||
if(tiddler.hasField("draft.of")) {
|
||||
// Report a fundamental problem
|
||||
console.warn(`TiddlyWiki: Plugins should not contain tiddlers with a 'draft.of' field: ${tiddler.fields.title}`);
|
||||
return;
|
||||
}
|
||||
// Define the module
|
||||
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
|
||||
}
|
||||
@@ -1913,7 +1905,7 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
|
||||
fileSize = fs.statSync(filepath).size,
|
||||
data;
|
||||
if(fileSize > $tw.config.maxEditFileSize) {
|
||||
data = "File " + filepath + " not loaded because it is too large";
|
||||
data = "File " + filepath + "not loaded because it is too large";
|
||||
console.log("Warning: " + data);
|
||||
ext = ".txt";
|
||||
} else {
|
||||
@@ -1984,41 +1976,22 @@ filepath: pathname of the directory containing the specification file
|
||||
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
var tiddlers = [];
|
||||
// Read the specification
|
||||
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"), function(e) {
|
||||
console.log("Warning: tiddlywiki.files in " + filepath + " invalid: " + e.message);
|
||||
return {};
|
||||
});
|
||||
|
||||
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
|
||||
// Helper to process a file
|
||||
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
|
||||
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
|
||||
type = (extInfo || {}).type || fields.type || "text/plain",
|
||||
typeInfo = $tw.config.contentTypeInfo[type] || {},
|
||||
pathname = path.resolve(filepath,filename),
|
||||
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8"),
|
||||
metadata = $tw.loadMetadataForFile(pathname) || {},
|
||||
fileTooLarge = false,
|
||||
text, fileTiddlers;
|
||||
|
||||
if("_canonical_uri" in fields) {
|
||||
text = "";
|
||||
} else if(fs.statSync(pathname).size > $tw.config.maxEditFileSize) {
|
||||
var msg = "File " + pathname + " not loaded because it is too large";
|
||||
console.log("Warning: " + msg);
|
||||
fileTooLarge = true;
|
||||
text = isTiddlerFile ? msg : "";
|
||||
} else {
|
||||
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8");
|
||||
}
|
||||
|
||||
fileTiddlers;
|
||||
if(isTiddlerFile) {
|
||||
fileTiddlers = $tw.wiki.deserializeTiddlers(fileTooLarge ? ".txt" : path.extname(pathname),text,metadata) || [];
|
||||
fileTiddlers = $tw.wiki.deserializeTiddlers(path.extname(pathname),text,metadata) || [];
|
||||
} else {
|
||||
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
|
||||
}
|
||||
var combinedFields = $tw.utils.extend({},fields,metadata);
|
||||
if(fileTooLarge && isTiddlerFile) {
|
||||
delete combinedFields.type; // type altered
|
||||
}
|
||||
$tw.utils.each(fileTiddlers,function(tiddler) {
|
||||
$tw.utils.each(combinedFields,function(fieldInfo,name) {
|
||||
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
|
||||
@@ -2093,7 +2066,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
} else if(tidInfo.suffix) {
|
||||
tidInfo.fields.text = {suffix: tidInfo.suffix};
|
||||
}
|
||||
tidInfo.fields = tidInfo.fields || {};
|
||||
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
|
||||
});
|
||||
// Process any listed directories
|
||||
@@ -2115,7 +2087,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
var thisPath = path.relative(filepath, files[t]),
|
||||
filename = path.basename(thisPath);
|
||||
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
||||
dirSpec.fields = dirSpec.fields || {};
|
||||
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
|
||||
}
|
||||
}
|
||||
@@ -2379,7 +2350,6 @@ $tw.loadTiddlersNode = function() {
|
||||
});
|
||||
// Load the core tiddlers
|
||||
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
|
||||
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.coreServerPath));
|
||||
// Load any extra plugins
|
||||
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
||||
if(name.charAt(0) === "+") { // Relative path to plugin
|
||||
@@ -2453,7 +2423,6 @@ $tw.boot.initStartup = function(options) {
|
||||
// System paths and filenames
|
||||
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
|
||||
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
|
||||
$tw.boot.coreServerPath = path.resolve($tw.boot.bootPath,"../core-server");
|
||||
// If there's no arguments then default to `--help`
|
||||
if($tw.boot.argv.length === 0) {
|
||||
$tw.boot.argv = ["--help"];
|
||||
@@ -2578,10 +2547,10 @@ $tw.boot.execStartup = function(options){
|
||||
if($tw.safeMode) {
|
||||
$tw.wiki.processSafeMode();
|
||||
}
|
||||
// Register typed modules from the tiddlers we've just loaded and any modules within plugins
|
||||
// Tiddlers should appear last so that they may overwrite shadows during module registration
|
||||
$tw.wiki.defineShadowModules();
|
||||
// Register typed modules from the tiddlers we've just loaded
|
||||
$tw.wiki.defineTiddlerModules();
|
||||
// And any modules within plugins
|
||||
$tw.wiki.defineShadowModules();
|
||||
// Make sure the crypto state tiddler is up to date
|
||||
if($tw.crypto) {
|
||||
$tw.crypto.updateCryptoStateTiddler();
|
||||
@@ -2650,13 +2619,11 @@ $tw.boot.executeNextStartupTask = function(callback) {
|
||||
$tw.boot.log(s.join(" "));
|
||||
// Execute task
|
||||
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
|
||||
const thenable = task.startup();
|
||||
if(thenable && typeof thenable.then === "function"){
|
||||
thenable.then(asyncTaskCallback);
|
||||
return true;
|
||||
} else {
|
||||
return asyncTaskCallback();
|
||||
task.startup();
|
||||
if(task.name) {
|
||||
$tw.boot.executedStartupModules[task.name] = true;
|
||||
}
|
||||
return $tw.boot.executeNextStartupTask(callback);
|
||||
} else {
|
||||
task.startup(asyncTaskCallback);
|
||||
return true;
|
||||
|
||||
19
community/people/LinOnetwo.tid
Normal file
19
community/people/LinOnetwo.tid
Normal file
@@ -0,0 +1,19 @@
|
||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEAAwEBAAAAAAAAAAAAAAAGAwQHAgUBAAMBAAAAAAAAAAAAAAAAAAACAwT/2gAMAwEAAhADEAAAAOfCWAMdKKetM4wOvY5OcvZnrYf/xAApEAACAQQBBAECBwAAAAAAAAABAgMABAURQQYSIVETFCIxMkJicYKh/9oACAEBAAE/AEtysaStr7mPaPeuazWdMM4gEnfPryW8hBUuZvou2RXRxyreBWPmgyNqs8f8MOQalhdY7Vz+R4/s/qfP+1edNi/zl7HDcFbmS3E8CcMR4INP0PkBhklIm+sZNtFtQiV0nj57Owl+dSrSTFgD6/CtH4VV9lU3oAbPngAVY389lc5URuUZkMxhnR4pvW0VwDqsP1FNmLWYqCpikMbngmliJNY+aKzyTxXS6lRAyg/u5rq+5x2RsuyTa3MQMlvKniRGThTUd1JYXUdzAwDvqVxGdRXMbfrVOD7HBrG3mNEsU8z98TRhl9eRzX//xAAcEQACAgIDAAAAAAAAAAAAAAABAgARAzESIVH/2gAIAQIBAT8ARuXZPsul3Eoje5lBQWBP/8QAGREAAwEBAQAAAAAAAAAAAAAAAAECEiER/9oACAEDAQE/AM98Lk7LJe20z//Z
|
||||
created: 20251110102157310
|
||||
first-sighting: 2019-03-01
|
||||
fullname: Lin Onetwo
|
||||
github: linonetwo
|
||||
homepage: https://wiki.onetwo.website/
|
||||
modified: 20251111184556193
|
||||
tags: Community/Person Community/Team/Contributors
|
||||
talk.tiddlywiki.org: linonetwo
|
||||
title: @linonetwo
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Since 2014, when I started college, I've been on a quest for a lifelong PKM tool. I cherish my life and all my experiences, and I don’t want to forget any of them. When I’m deeply focused on a task, it’s easy to lose sight of other important parts of my life—so I needed a system to help me stay balanced.
|
||||
|
||||
Early on, I tried TiddlyWiki several times, but I was initially put off by its save mechanism and markup editing. That changed when I discovered an auto-backup script, which gave me the confidence to fully commit. Over time, I improved the script and eventually transitioned to using TidGi-Desktop and TidGi-Mobile.
|
||||
|
||||
Today, my TiddlyWiki holds all my game design ideas and progress logs—it has truly become my second brain. With the help of LLM-powered programming tools, I’ve enhanced it with numerous plugins, allowing me to manage my mind in a more programmable and structured way. As a game developer, TiddlyWiki isn't the core of my professional work; But I've invested so much time because it's fundamentally about upgrading my mind.
|
||||
|
||||
Most of my notes are open by default and shared publicly on my homepage as a digital garden.
|
||||
25
community/people/PMario.tid
Normal file
25
community/people/PMario.tid
Normal file
@@ -0,0 +1,25 @@
|
||||
avatar: UklGRiwIAABXRUJQVlA4WAoAAAAwAAAAPwAAPwAASUNDUCACAAAAAAIgbGNtcwRAAABtbnRyR1JBWVhZWiAH6QALAAoACwADAAZhY3NwTVNGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZkZXNjAAAAzAAAAG5jcHJ0AAABPAAAADZ3dHB0AAABdAAAABRrVFJDAAABiAAAACBkbW5kAAABqAAAACRkbWRkAAABzAAAAFJtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFIAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA81EAAQAAAAEWzHBhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbbWx1YwAAAAAAAAABAAAADGVuVVMAAAAIAAAAHABHAEkATQBQbWx1YwAAAAAAAAABAAAADGVuVVMAAAA2AAAAHABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAVlA4TOYFAAAvP8APEDWGgbRtWv+yt/0WImICOBvWn1C4dFi1bStbvpY8Qg2ePANNNAMh3N2db/7A91/7CHBvBBRr25ZFH+4k98ihkqi2CP4tsANvX8a+8y8Ct04dn0nuUt39ZiBJkowqt911M+MJ1G3bNiZJr1iP0DZ+2bbdadsqprOjAqmoUIX9hf3Fl5/uPYV7I3OMeoFzIvrvwG0kRUr3zPLdYMMXaqrMMsp0K4fufKO6c2hFV5Zh7kRROZX0PSCmB/3KWQwpuiekWelSRZDW94d0q750NrxavpFn1eLNQ9EV8nWlmAET6Q8lrCRTcjFLlLImluK3iXJW/hT47KGklS8OlzWUtXLFYDRCSS74ojUjxggqKMoxd6A1lTCyvsvyzC5/d7BsCHb7yIcHyrX2yR/NPnsAdRT2i0Pwp/o0Il6ix8hsRAuJmQgcr4KREfAiMgUVm9KqmfSxL5pOJspVwwTiV6jiIAg1RMhHpERhbvwgGI34Hc49T7UeKZtXwEqJ+BAaoBneperJH0POs1u4dufwv8Gf+qcOfjyvX6ZIVgxE0Rw87YF3BSc9c7jsXfdjOBG7FwmSb39pfGRwu8IuvUjJNoTpFzkEvDg6W3Qt/9nf99ZXPy8HM43IweTKyNR+WVatXcWWyakBksj9cqW+QetplcjsKElvZH/zuOO/PrCx//tL3/6x/O/C1PZZvSKuulLcS4l8M1ewGPR6ef5sllXW2eGQZ7hVSEZiPmcqrSS8e2ElX8o7t1fvB9LFetmEx5hx1Xuye2PpfjZnSjj7QfKTB3bZZo05Zvh6YuivX24cpc8+ddvADWG9odrSwFalVurxUiidDHmTiaoNkkh2gjbcpxMiAbd39aVP119/N9k4+euNKfcNjwaPhZEuUupUsJrHchw1LkPrRC9bQKa3M8Mj/xx903drdnHMpbirj1ENsUre0oo3N+7gat+2ZctKdsIUYc21sRu+Ucdhn+P7DyarftW00iu3Tmbv+hTfdCTmyaIPT4PrYZDFtBN2W8S9m4oTB5Z2P3Oe7weKjVBq86kXX/r0+WuvTAzfjqm1hsYRPWlbxm4n3IaeGOJEizv8orH9w5ejjmSrfOuEq/HxT6eDemtsZ/HTvvG1/8iVspxZILrlkz/cdsIbIroOgJileFSty2xiHNW5t9fbHJ3ze87bp5T9vc8RuqMB0ReDSt464R/BJxspvgpEsrVAJMTsYg2QovPTOHrvQ9et/S2Xx+40z7dY4JBX0Pz/ElH/T73U2DkK8EiqC9hM/zV3frQfzjaAqO16s1l6xCUXnBFlYxyIer3eEdth7u5xsHKxWoGLqzY3wIULt9G3K6soei9jZ+UcF+Ka3M/II9EUWrJ/LLxy+Q9xIh0vOl3NZCrVnBsuFUTOSnJnSioRWZ9q4g+ZDk5XVORoW2qX2hbIkna3JOrdR3jmpHVLovUkLES6grRO010u0GkDlX7SpH1DQ64Wl2zaSUJv1Mtti2G7kx5IyftWMhfDlGClcxvIUhP5crhp9LIb1Vne187oSAWxelcR/kXjYQTZboW+Oj1pqF0gmfZhSDD6bSgzGWrw3s7QLNtCV+2uatYrd/aFtjDI8R52e/DdyKgRKXBhEak3Ev50+GCUA9EFUor39htVMxmWvW8AM6ptG416rZvdWn+MarIEyH5r6ruZSrx8XrWDP370vbfTjqpmZGIbiFPFoihc4jcrlYi9p3ndSuymZ+XLaKza/P/HUWHn5Axdkd9OjBskY0+pIlz4AlFPFs+aStK5PBIRR4MVVJDihsy4JdEA4pVcrVqMZDyL2/8aYocikEAR9Xjc1BNG9zEiJG7n/cGyrtnblkClBhEgMW4Kx21BEBGJjLa0hcOGmTK64KsKLfKr9QyQELclxY3hqowTIZKdZNTSS5BWiBPlKxDWBVSS41bOepkhTkhGDajLfLyUBOKlkMHPgOhx3JoRN/cEiRgSWdgF2yCyDQu4IcbNo8ftTzxveOJ5y+h509h52+h549h569h587/M20f/b1AB
|
||||
created: 20251110102157310
|
||||
first-sighting: 2009-11-14
|
||||
fullname: Mario Pietsch
|
||||
github: pmario
|
||||
homepage: https://wikilabs.github.io/
|
||||
modified: 20251110124935183
|
||||
tags: Community/Person Community/Team/Contributors
|
||||
talk.tiddlywiki.org: pmario
|
||||
title: @pmario
|
||||
type: text/vnd.tiddlywiki
|
||||
youtube: https://www.youtube.com/@pmario
|
||||
|
||||
''Hi, My name is Mario Pietsch''. Back in 2009 I was ''searching'' for ''a simple presentation tool'' and discovered ~TiddlyWiki Classic, Monkey Pirate ~TiddlyWiki ([[MPTW|https://mptw.tiddlyspot.com/]]) with ~TagglyTagging, Eric Shulman's ~TiddlyTools, Saq Imtiaz's navigation macros, and more. --- ''I was captivated''.
|
||||
|
||||
After a deep dive, I combined these elements into my own "Presentation Manager", along [[3 step by step tutorials|https://groups.google.com/g/tiddlywiki/c/qG_tZ1x0MEU/m/-vLA0luMicYJ]] to help others build it.
|
||||
|
||||
Thanks to ''the positive spirit'' of the ~TiddlyWiki community, I am proud to be part of it since 2009.
|
||||
|
||||
When Jeremy started developing ~TiddlyWiki 5 on ~GitHub, I joined in—opening [[issue no. 1|https://github.com/TiddlyWiki/TiddlyWiki5/issues/1]] all the way up to 13. For what that’s good ;) Since then, I have submitted nearly 600 pull requests and more than 500 issues, many of which have been merged or resolved.
|
||||
|
||||
My ~TiddlyWiki 5 "laboratory" is at https://wikilabs.github.io, and I also share content on my ''~YouTube'' channel: https://www.youtube.com/@pmario
|
||||
|
||||
Have fun!<br>
|
||||
Mario
|
||||
19
community/project/teams/Developer Experience Team.tid
Normal file
19
community/project/teams/Developer Experience Team.tid
Normal file
@@ -0,0 +1,19 @@
|
||||
title: Developer Experience Team
|
||||
tags: Community/Team
|
||||
modified: 20251109200632671
|
||||
created: 20251109200632671
|
||||
leader: @pmario
|
||||
team: @saqimtiaz
|
||||
|
||||
The Developer Experience Team improves the experience of software contributors to the TiddlyWiki project. This includes enhancing documentation, streamlining contribution processes, and providing tools and resources to help developers effectively contribute to TiddlyWiki.
|
||||
|
||||
Tools and resources managed by the Developer Experience Team include:
|
||||
|
||||
* Advising and assisting contributors, particularly new developers
|
||||
* Maintenance of developer-focused documentation on the https://tiddlywiki.com/dev/ site, including:
|
||||
** Development environment setup guides
|
||||
** Code review processes and best practices
|
||||
** Contribution guidelines and documentation
|
||||
* Continuous integration and deployment scripts providing feedback on pull requests
|
||||
* Devising and implementing labelling systems for issues and pull requests
|
||||
* Automation scripts to simplify common development tasks
|
||||
@@ -1,8 +1,8 @@
|
||||
title: Infrastructure Team
|
||||
tags: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
modified: 20251110133437795
|
||||
tags: Community/Team
|
||||
team: @MotovunJack
|
||||
title: Infrastructure Team
|
||||
|
||||
The Infrastructure Team is responsible for maintaining and improving the infrastructure that supports the TiddlyWiki project. This includes the hosting, deployment, and management of the TiddlyWiki websites and services, as well as the tools and systems used by the TiddlyWiki community.
|
||||
|
||||
@@ -12,3 +12,4 @@ The infrastructure includes:
|
||||
* github.com/TiddlyWiki
|
||||
* tiddlywiki.com DNS
|
||||
* Netlify account for PR previews
|
||||
* edit.tiddlywiki.com
|
||||
11
community/project/teams/Quality Assurance Team.tid
Normal file
11
community/project/teams/Quality Assurance Team.tid
Normal file
@@ -0,0 +1,11 @@
|
||||
title: Quality Assurance Team
|
||||
created: 20251112125742296
|
||||
modified: 20251112125742296
|
||||
tags: Community/Team
|
||||
team:
|
||||
leader: @Leilei332
|
||||
|
||||
title: Quality Assurance Team
|
||||
|
||||
The Quality Assurance Team is responsible for ensuring the quality and reliability of TiddlyWiki releases. This includes reviewing code submissions, testing new features, identifying bugs, and verifying that fixes are effective.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
title: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Infrastructure Team]] [[Succession Team]]
|
||||
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[Quality Assurance Team]] [[Infrastructure Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Succession Team]]
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"title": "$:/core-server",
|
||||
"name": "Core Server Components",
|
||||
"description": "TiddlyWiki5 core server components",
|
||||
"author": "JeremyRuston",
|
||||
"core-version": ">=5.0.0",
|
||||
"platform": "server",
|
||||
"plugin-priority": "0",
|
||||
"list": "readme",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
title: $:/core-server/readme
|
||||
|
||||
This plugin contains TiddlyWiki's core components that are only needed on the server, comprising:
|
||||
|
||||
* Commands
|
||||
* HTTP server code
|
||||
* Utility functions for server
|
||||
@@ -1,73 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/routes/get-file.js
|
||||
type: application/javascript
|
||||
module-type: route
|
||||
|
||||
GET /files/:filepath
|
||||
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
|
||||
exports.path = /^\/files\/(.+)$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var path = require("path"),
|
||||
fs = require("fs"),
|
||||
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
baseFilename = path.resolve(state.boot.wikiPath,"files"),
|
||||
filename = path.resolve(baseFilename,suppliedFilename),
|
||||
extension = path.extname(filename);
|
||||
// Check that the filename is inside the wiki files folder
|
||||
if(path.relative(baseFilename,filename).indexOf("..") === 0) {
|
||||
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
||||
}
|
||||
fs.stat(filename, function(err, stats) {
|
||||
if(err) {
|
||||
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
||||
} else {
|
||||
var type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream"),
|
||||
responseHeaders = {
|
||||
"Content-Type": type,
|
||||
"Accept-Ranges": "bytes"
|
||||
};
|
||||
var rangeHeader = request.headers.range,
|
||||
stream;
|
||||
if(rangeHeader) {
|
||||
// Handle range requests
|
||||
var parts = rangeHeader.replace(/bytes=/, "").split("-"),
|
||||
start = parseInt(parts[0], 10),
|
||||
end = parts[1] ? parseInt(parts[1], 10) : stats.size - 1;
|
||||
// Validate start and end
|
||||
if(isNaN(start) || isNaN(end) || start < 0 || end < start || end >= stats.size) {
|
||||
responseHeaders["Content-Range"] = "bytes */" + stats.size;
|
||||
return response.writeHead(416, responseHeaders).end();
|
||||
}
|
||||
var chunksize = (end - start) + 1;
|
||||
responseHeaders["Content-Range"] = "bytes " + start + "-" + end + "/" + stats.size;
|
||||
responseHeaders["Content-Length"] = chunksize;
|
||||
response.writeHead(206, responseHeaders);
|
||||
stream = fs.createReadStream(filename, {start: start, end: end});
|
||||
} else {
|
||||
responseHeaders["Content-Length"] = stats.size;
|
||||
response.writeHead(200, responseHeaders);
|
||||
stream = fs.createReadStream(filename);
|
||||
}
|
||||
// Common stream error handling
|
||||
stream.on("error", function(err) {
|
||||
if(!response.headersSent) {
|
||||
response.writeHead(500, {"Content-Type": "text/plain"});
|
||||
response.end("Read error");
|
||||
} else {
|
||||
response.destroy();
|
||||
}
|
||||
});
|
||||
stream.pipe(response);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -147,7 +147,7 @@ Settings/AutoSave/Disabled/Description: Do not save changes automatically
|
||||
Settings/AutoSave/Enabled/Description: Save changes automatically
|
||||
Settings/AutoSave/Hint: Attempt to automatically save changes during editing when using a supporting saver
|
||||
Settings/CamelCase/Caption: Camel Case Wiki Links
|
||||
Settings/CamelCase/Hint: Requires reload to take effect
|
||||
Settings/CamelCase/Hint: You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect
|
||||
Settings/CamelCase/Description: Enable automatic ~CamelCase linking
|
||||
Settings/Caption: Settings
|
||||
Settings/EditorToolbar/Caption: Editor Toolbar
|
||||
|
||||
@@ -99,18 +99,16 @@ Commander.prototype.executeNextCommand = function() {
|
||||
}
|
||||
}
|
||||
if(command.info.synchronous) {
|
||||
// Synchronous command (await thenables)
|
||||
// Synchronous command
|
||||
c = new command.Command(params,this);
|
||||
err = c.execute();
|
||||
if(err && typeof err.then === "function") {
|
||||
err.then(e => { e ? this.callback(e) : this.executeNextCommand(); });
|
||||
} else if(err) {
|
||||
if(err) {
|
||||
this.callback(err);
|
||||
} else {
|
||||
this.executeNextCommand();
|
||||
}
|
||||
} else {
|
||||
// Asynchronous command (await thenables)
|
||||
// Asynchronous command
|
||||
c = new command.Command(params,this,function(err) {
|
||||
if(err) {
|
||||
self.callback(err);
|
||||
@@ -119,9 +117,7 @@ Commander.prototype.executeNextCommand = function() {
|
||||
}
|
||||
});
|
||||
err = c.execute();
|
||||
if(err && typeof err.then === "function") {
|
||||
err.then(e => { if(e) this.callback(e); });
|
||||
} else if(err) {
|
||||
if(err) {
|
||||
this.callback(err);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,6 @@ WikiFolderMaker.prototype.tiddlersToIgnore = [
|
||||
"$:/boot/boot.js",
|
||||
"$:/boot/bootprefix.js",
|
||||
"$:/core",
|
||||
"$:/core-server",
|
||||
"$:/library/sjcl.js",
|
||||
"$:/temp/info-plugin"
|
||||
];
|
||||
@@ -34,7 +34,7 @@ function FramedEngine(options) {
|
||||
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
|
||||
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
|
||||
this.iframeDoc.open();
|
||||
this.iframeDoc.write("<!DOCTYPE html><html><head><meta name='color-scheme' content='" + colorScheme + "'></head><body></body></html>");
|
||||
this.iframeDoc.write("<meta name='color-scheme' content='" + colorScheme + "'>");
|
||||
this.iframeDoc.close();
|
||||
// Style the iframe
|
||||
this.iframeNode.className = this.dummyTextArea.className;
|
||||
|
||||
@@ -68,7 +68,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
// Fix height
|
||||
this.engine.fixHeight();
|
||||
// Focus if required
|
||||
if($tw.browser && (this.editFocus === "true" || this.editFocus === "yes") && !$tw.utils.hasClass(this.parentDomNode.ownerDocument.activeElement,"tc-keep-focus")) {
|
||||
if(this.editFocus === "true" || this.editFocus === "yes") {
|
||||
this.engine.focus();
|
||||
}
|
||||
// Add widget message listeners
|
||||
|
||||
@@ -217,10 +217,6 @@ function makeNumericReducingOperator(fnCalc,initialValue,fnFinal) {
|
||||
source(function(tiddler,title) {
|
||||
result.push($tw.utils.parseNumber(title));
|
||||
});
|
||||
// We return an empty array if there are no input titles
|
||||
if(result.length === 0) {
|
||||
return [];
|
||||
}
|
||||
var value = result.reduce(function(accumulator,currentValue) {
|
||||
return fnCalc(accumulator,currentValue);
|
||||
},initialValue);
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/info/windowdimensions.js
|
||||
type: application/javascript
|
||||
module-type: info
|
||||
\*/
|
||||
|
||||
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
|
||||
if(!$tw.browser) {
|
||||
return [];
|
||||
}
|
||||
|
||||
class WindowDimensionsTracker {
|
||||
constructor(updateCallback) {
|
||||
this.updateCallback = updateCallback;
|
||||
this.resizeHandlers = new Map();
|
||||
this.dimensionsInfo = [
|
||||
["outer/width", win => win.outerWidth],
|
||||
["outer/height", win => win.outerHeight],
|
||||
["inner/width", win => win.innerWidth],
|
||||
["inner/height", win => win.innerHeight],
|
||||
["client/width", win => win.document.documentElement.clientWidth],
|
||||
["client/height", win => win.document.documentElement.clientHeight]
|
||||
];
|
||||
}
|
||||
|
||||
buildTiddlers(win,windowId) {
|
||||
const prefix = `$:/info/browser/window/${windowId}/`;
|
||||
return this.dimensionsInfo.map(([suffix, getter]) => ({
|
||||
title: prefix + suffix,
|
||||
text: String(getter(win))
|
||||
}));
|
||||
}
|
||||
|
||||
clearTiddlers(windowId) {
|
||||
const prefix = `$:/info/browser/window/${windowId}/`,
|
||||
deletions = this.dimensionsInfo.map(([suffix]) => prefix + suffix);
|
||||
this.updateCallback([], deletions);
|
||||
}
|
||||
|
||||
getUpdateHandler(win,windowId) {
|
||||
let scheduled = false;
|
||||
return () => {
|
||||
if(!scheduled) {
|
||||
scheduled = true;
|
||||
requestAnimationFrame(() => {
|
||||
this.updateCallback(this.buildTiddlers(win,windowId), []);
|
||||
scheduled = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
trackWindow(win,windowId) {
|
||||
const handler = this.getUpdateHandler(win, windowId);
|
||||
handler(); // initial update
|
||||
win.addEventListener("resize",handler,{passive:true});
|
||||
this.resizeHandlers.set(windowId,{win, handler});
|
||||
}
|
||||
|
||||
untrackWindow(windowId) {
|
||||
const entry = this.resizeHandlers.get(windowId);
|
||||
if(entry) {
|
||||
entry.win.removeEventListener("resize", entry.handler);
|
||||
this.resizeHandlers.delete(windowId);
|
||||
}
|
||||
this.clearTiddlers(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
const tracker = new WindowDimensionsTracker(updateInfoTiddlersCallback);
|
||||
|
||||
// Track main window
|
||||
tracker.trackWindow(window,"system/main");
|
||||
|
||||
// Hook into event bus for user windows
|
||||
if($tw.eventBus) {
|
||||
$tw.eventBus.on("window:opened", ({window: win, windowID}) => {
|
||||
tracker.trackWindow(win, "user/" + windowID);
|
||||
});
|
||||
$tw.eventBus.on("window:closed", ({windowID}) => {
|
||||
tracker.untrackWindow("user/" + windowID);
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
@@ -7,34 +7,23 @@ The audio parser parses an audio tiddler into an embeddable HTML element
|
||||
|
||||
\*/
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var AudioParser = function(type,text,options) {
|
||||
var element = {
|
||||
type: "element",
|
||||
tag: "$audio", // Using $audio to enable widget interception
|
||||
tag: "audio",
|
||||
attributes: {
|
||||
controls: {type: "string", value: "controls"},
|
||||
style: {type: "string", value: "width: 100%; object-fit: contain"}
|
||||
}
|
||||
};
|
||||
|
||||
// Pass through source information
|
||||
},
|
||||
src;
|
||||
if(options._canonical_uri) {
|
||||
element.attributes.src = {type: "string", value: options._canonical_uri};
|
||||
element.attributes.type = {type: "string", value: type};
|
||||
} else if(text) {
|
||||
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
|
||||
element.attributes.type = {type: "string", value: type};
|
||||
}
|
||||
|
||||
// Pass through tiddler title if available
|
||||
if(options.title) {
|
||||
element.attributes.tiddler = {type: "string", value: options.title};
|
||||
}
|
||||
|
||||
this.tree = [element];
|
||||
this.source = text;
|
||||
this.type = type;
|
||||
@@ -44,4 +33,3 @@ exports["audio/ogg"] = AudioParser;
|
||||
exports["audio/mpeg"] = AudioParser;
|
||||
exports["audio/mp3"] = AudioParser;
|
||||
exports["audio/mp4"] = AudioParser;
|
||||
|
||||
@@ -82,7 +82,6 @@ exports.parseTokenString = function(source,pos,token) {
|
||||
|
||||
/*
|
||||
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
|
||||
Use the "Y" (sticky) flag to avoid searching the entire rest of the string
|
||||
*/
|
||||
exports.parseTokenRegExp = function(source,pos,reToken) {
|
||||
var node = {
|
||||
@@ -173,7 +172,7 @@ exports.parseMacroParameter = function(source,pos) {
|
||||
start: pos
|
||||
};
|
||||
// Define our regexp
|
||||
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
|
||||
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for the parameter
|
||||
@@ -241,7 +240,7 @@ exports.parseMacroInvocation = function(source,pos) {
|
||||
params: []
|
||||
};
|
||||
// Define our regexps
|
||||
const reMacroName = /([^\s>"'=]+)/y;
|
||||
var reMacroName = /([^\s>"'=]+)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double less than sign
|
||||
@@ -278,7 +277,7 @@ exports.parseFilterVariable = function(source) {
|
||||
params: [],
|
||||
},
|
||||
pos = 0,
|
||||
reName = /([^\s"']+)/y;
|
||||
reName = /([^\s"']+)/g;
|
||||
// If there is no whitespace or it is an empty string then there are no macro parameters
|
||||
if(/^\S*$/.test(source)) {
|
||||
node.name = source;
|
||||
@@ -303,11 +302,11 @@ exports.parseAttribute = function(source,pos) {
|
||||
start: pos
|
||||
};
|
||||
// Define our regexps
|
||||
const reAttributeName = /([^\/\s>"'`=]+)/y,
|
||||
reUnquotedAttribute = /([^\/\s<>"'`=]+)/y,
|
||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/y,
|
||||
reIndirectValue = /\{\{([^\}]+)\}\}/y,
|
||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/y;
|
||||
var reAttributeName = /([^\/\s>"'`=]+)/g,
|
||||
reUnquotedAttribute = /([^\/\s<>"'`=]+)/g,
|
||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
|
||||
reIndirectValue = /\{\{([^\}]+)\}\}/g,
|
||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Get the attribute name
|
||||
|
||||
@@ -39,7 +39,7 @@ exports.parse = function() {
|
||||
// Return the classed span
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "s",
|
||||
tag: "strike",
|
||||
children: tree
|
||||
}];
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ exports.parse = function() {
|
||||
// Advance the parser position to past the tag
|
||||
this.parser.pos = tag.end;
|
||||
// Check for an immediately following double linebreak
|
||||
var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y);
|
||||
var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g);
|
||||
// Set whether we're in block mode
|
||||
tag.isBlock = this.is.block || hasLineBreak;
|
||||
// Parse the body if we need to
|
||||
@@ -100,7 +100,7 @@ exports.parseTag = function(source,pos,options) {
|
||||
orderedAttributes: []
|
||||
};
|
||||
// Define our regexps
|
||||
const reTagName = /([a-zA-Z0-9\-\$\.]+)/y;
|
||||
var reTagName = /([a-zA-Z0-9\-\$\.]+)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a less than sign
|
||||
@@ -148,7 +148,7 @@ exports.parseTag = function(source,pos,options) {
|
||||
pos = token.end;
|
||||
// Check for a required line break
|
||||
if(options.requireLineBreak) {
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y);
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g);
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ exports.parseImage = function(source,pos) {
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Get the source up to the terminating `]]`
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/y);
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g);
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -23,27 +23,6 @@ exports.init = function(parser) {
|
||||
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
Reject the match if we don't have a template or text reference
|
||||
*/
|
||||
exports.findNextMatch = function(startPos) {
|
||||
this.matchRegExp.lastIndex = startPos;
|
||||
this.match = this.matchRegExp.exec(this.parser.source);
|
||||
if(this.match) {
|
||||
var template = $tw.utils.trim(this.match[2]),
|
||||
textRef = $tw.utils.trim(this.match[1]);
|
||||
// Bail if we don't have a template or text reference
|
||||
if(!template && !textRef) {
|
||||
return undefined;
|
||||
} else {
|
||||
return this.match.index;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return this.match ? this.match.index : undefined;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
@@ -23,27 +23,6 @@ exports.init = function(parser) {
|
||||
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
Reject the match if we don't have a template or text reference
|
||||
*/
|
||||
exports.findNextMatch = function(startPos) {
|
||||
this.matchRegExp.lastIndex = startPos;
|
||||
this.match = this.matchRegExp.exec(this.parser.source);
|
||||
if(this.match) {
|
||||
var template = $tw.utils.trim(this.match[2]),
|
||||
textRef = $tw.utils.trim(this.match[1]);
|
||||
// Bail if we don't have a template or text reference
|
||||
if(!template && !textRef) {
|
||||
return undefined;
|
||||
} else {
|
||||
return this.match.index;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return this.match ? this.match.index : undefined;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
@@ -35,9 +35,7 @@ DownloadSaver.prototype.save = function(text,method,callback,options) {
|
||||
}
|
||||
// Set up the link
|
||||
var link = document.createElement("a");
|
||||
// We prefer Blobs if they're available, unless we're dealing with a tiddler type declaring itself full of base64 encoded content.
|
||||
// Then we use data urls, because browsers will know to decode the stream and download the actual binary file as intended.
|
||||
if(Blob !== undefined && !type.includes(";base64")) {
|
||||
if(Blob !== undefined) {
|
||||
var blob = new Blob([text], {type: type});
|
||||
link.setAttribute("href", URL.createObjectURL(blob));
|
||||
} else {
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/postmessage.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Handles saving changes via window.postMessage() to the window.parent
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var PostMessageSaver = function(wiki) {
|
||||
this.publisher = new $tw.utils.BrowserMessagingPublisher({type: "SAVE"});
|
||||
};
|
||||
|
||||
PostMessageSaver.prototype.save = function(text,method,callback,options) {
|
||||
// Fail if the publisher hasn't been fully initialised
|
||||
if(!this.publisher.canSend()) {
|
||||
return false;
|
||||
}
|
||||
// Send the save request
|
||||
this.publisher.send({
|
||||
verb: "SAVE",
|
||||
body: text
|
||||
},function(err) {
|
||||
if(err) {
|
||||
callback("PostMessageSaver Error: " + err);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
// Indicate that we handled the save
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
PostMessageSaver.prototype.info = {
|
||||
name: "postmessage",
|
||||
capabilities: ["save", "autosave"],
|
||||
priority: 100
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
// Provisionally say that we can save
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new PostMessageSaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -8,14 +8,10 @@ DELETE /recipes/default/tiddlers/:title
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["DELETE"];
|
||||
exports.method = "DELETE";
|
||||
|
||||
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
||||
state.wiki.deleteTiddler(title);
|
||||
@@ -8,14 +8,10 @@ GET /favicon.ico
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/favicon.ico$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var buffer = state.wiki.getTiddlerText("$:/favicon.ico","");
|
||||
state.sendResponse(200,{"Content-Type": "image/x-icon"},buffer,"base64");
|
||||
42
core/modules/server/routes/get-file.js
Normal file
42
core/modules/server/routes/get-file.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/routes/get-file.js
|
||||
type: application/javascript
|
||||
module-type: route
|
||||
|
||||
GET /files/:filepath
|
||||
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/files\/(.+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var path = require("path"),
|
||||
fs = require("fs"),
|
||||
util = require("util"),
|
||||
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
baseFilename = path.resolve(state.boot.wikiPath,"files"),
|
||||
filename = path.resolve(baseFilename,suppliedFilename),
|
||||
extension = path.extname(filename);
|
||||
// Check that the filename is inside the wiki files folder
|
||||
if(path.relative(baseFilename,filename).indexOf("..") !== 0) {
|
||||
// Send the file
|
||||
fs.readFile(filename,function(err,content) {
|
||||
var status,content,type = "text/plain";
|
||||
if(err) {
|
||||
console.log("Error accessing file " + filename + ": " + err.toString());
|
||||
status = 404;
|
||||
content = "File '" + suppliedFilename + "' not found";
|
||||
} else {
|
||||
status = 200;
|
||||
content = content;
|
||||
type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream");
|
||||
}
|
||||
state.sendResponse(status,{"Content-Type": type},content);
|
||||
});
|
||||
} else {
|
||||
state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
||||
}
|
||||
};
|
||||
@@ -8,14 +8,10 @@ GET /
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
|
||||
responseHeaders = {
|
||||
@@ -8,14 +8,10 @@ GET /login-basic -- force a Basic Authentication challenge
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/login-basic$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
if(!state.authenticatedUsername) {
|
||||
// Challenge if there's no username
|
||||
@@ -8,14 +8,10 @@ GET /status
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/status$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var text = JSON.stringify({
|
||||
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
||||
@@ -8,14 +8,10 @@ GET /:title
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/([^\/]+)$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
tiddler = state.wiki.getTiddler(title);
|
||||
@@ -8,14 +8,10 @@ GET /recipes/default/tiddlers/:title
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
tiddler = state.wiki.getTiddler(title),
|
||||
@@ -10,14 +10,10 @@ GET /recipes/default/tiddlers.json?filter=<filter>
|
||||
|
||||
var DEFAULT_FILTER = "[all[tiddlers]!is[system]sort[title]]";
|
||||
|
||||
exports.methods = ["GET"];
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/recipes\/default\/tiddlers.json$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var filter = state.queryParameters.filter || DEFAULT_FILTER;
|
||||
if(state.wiki.getTiddlerText("$:/config/Server/AllowAllExternalFilters") !== "yes") {
|
||||
@@ -8,14 +8,10 @@ PUT /recipes/default/tiddlers/:title
|
||||
\*/
|
||||
"use strict";
|
||||
|
||||
exports.methods = ["PUT"];
|
||||
exports.method = "PUT";
|
||||
|
||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.info = {
|
||||
priority: 100
|
||||
};
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
fields = $tw.utils.parseJSONSafe(state.data);
|
||||
@@ -74,11 +74,6 @@ function Server(options) {
|
||||
// console.log("Loading server route " + title);
|
||||
self.addRoute(routeDefinition);
|
||||
});
|
||||
this.routes.sort((a, b) => {
|
||||
const priorityA = a.info?.priority ?? 100,
|
||||
priorityB = b.info?.priority ?? 100;
|
||||
return priorityB - priorityA;
|
||||
});
|
||||
// Initialise the http vs https
|
||||
this.listenOptions = null;
|
||||
this.protocol = "http";
|
||||
@@ -222,7 +217,7 @@ Server.prototype.findMatchingRoute = function(request,state) {
|
||||
} else {
|
||||
match = potentialRoute.path.exec(pathname);
|
||||
}
|
||||
if(match && (potentialRoute.methods?.includes(request.method) || potentialRoute.method === request.method)) {
|
||||
if(match && request.method === potentialRoute.method) {
|
||||
state.params = [];
|
||||
for(var p=1; p<match.length; p++) {
|
||||
state.params.push(match[p]);
|
||||
@@ -1,46 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/startup/eventbus.js
|
||||
type: application/javascript
|
||||
module-type: startup
|
||||
|
||||
Event bus for cross module communication
|
||||
\*/
|
||||
|
||||
exports.name = "eventbus";
|
||||
exports.platforms = ["browser"];
|
||||
exports.before = ["windows"];
|
||||
exports.synchronous = true;
|
||||
|
||||
$tw.eventBus = {
|
||||
listenersMap: new Map(),
|
||||
|
||||
on(event,handler) {
|
||||
if(!this.listenersMap.has(event)) {
|
||||
this.listenersMap.set(event,new Set());
|
||||
}
|
||||
const listeners = this.listenersMap.get(event);
|
||||
listeners.add(handler);
|
||||
},
|
||||
|
||||
off(event,handler) {
|
||||
const listeners = this.listenersMap.get(event);
|
||||
if(listeners) {
|
||||
listeners.delete(handler);
|
||||
}
|
||||
},
|
||||
|
||||
once(event,handler) {
|
||||
const wrapper = (...args) => {
|
||||
handler(...args);
|
||||
this.off(event, wrapper);
|
||||
};
|
||||
this.on(event, wrapper);
|
||||
},
|
||||
|
||||
emit(event,data) {
|
||||
const listeners = this.listenersMap.get(event);
|
||||
if(listeners) {
|
||||
listeners.forEach(fn => fn(data));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -19,16 +19,6 @@ exports.synchronous = true;
|
||||
var FAVICON_TITLE = "$:/favicon.ico";
|
||||
|
||||
exports.startup = function() {
|
||||
var setFavicon = function() {
|
||||
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
||||
if(tiddler) {
|
||||
var faviconLink = document.getElementById("faviconLink"),
|
||||
dataURI = $tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri);
|
||||
faviconLink.setAttribute("href",dataURI);
|
||||
$tw.faviconPublisher.send({verb: "FAVICON",body: dataURI});
|
||||
}
|
||||
}
|
||||
$tw.faviconPublisher = new $tw.utils.BrowserMessagingPublisher({type: "FAVICON", onsubscribe: setFavicon});
|
||||
// Set up the favicon
|
||||
setFavicon();
|
||||
// Reset the favicon when the tiddler changes
|
||||
@@ -38,3 +28,11 @@ exports.startup = function() {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function setFavicon() {
|
||||
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
||||
if(tiddler) {
|
||||
var faviconLink = document.getElementById("faviconLink");
|
||||
faviconLink.setAttribute("href",$tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,17 +19,11 @@ var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
|
||||
|
||||
exports.startup = function() {
|
||||
// Function to bake the info plugin with new tiddlers
|
||||
// additions: array of tiddler field objects
|
||||
// removals: array of titles to remove
|
||||
var updateInfoPlugin = function(additions = [], removals = []) {
|
||||
var updateInfoPlugin = function(tiddlerFieldsArray) {
|
||||
// Get the existing tiddlers
|
||||
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
|
||||
$tw.utils.each(removals,function(title) {
|
||||
if(json.tiddlers[title]) {
|
||||
delete json.tiddlers[title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(additions,function(fields) {
|
||||
// Add the new ones
|
||||
$tw.utils.each(tiddlerFieldsArray,function(fields) {
|
||||
if(fields && fields.title) {
|
||||
json.tiddlers[fields.title] = fields;
|
||||
}
|
||||
@@ -53,7 +47,7 @@ exports.startup = function() {
|
||||
}
|
||||
});
|
||||
updateInfoPlugin(tiddlerFieldsArray);
|
||||
$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||
var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
|
||||
$tw.wiki.unpackPluginTiddlers();
|
||||
};
|
||||
|
||||
@@ -31,7 +31,5 @@ exports.startup = function() {
|
||||
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
||||
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
|
||||
$tw.wiki.initParsers();
|
||||
if($tw.node) {
|
||||
$tw.Commander.initCommands();
|
||||
}
|
||||
$tw.Commander.initCommands();
|
||||
};
|
||||
|
||||
@@ -33,15 +33,10 @@ exports.startup = function() {
|
||||
});
|
||||
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
||||
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
||||
var publishTitle = function() {
|
||||
$tw.titlePublisher.send({verb: "PAGETITLE",body: document.title});
|
||||
document.title = $tw.titleContainer.textContent;
|
||||
};
|
||||
$tw.titlePublisher = new $tw.utils.BrowserMessagingPublisher({type: "PAGETITLE", onsubscribe: publishTitle});
|
||||
publishTitle();
|
||||
document.title = $tw.titleContainer.textContent;
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
|
||||
publishTitle();
|
||||
document.title = $tw.titleContainer.textContent;
|
||||
}
|
||||
});
|
||||
// Set up the styles
|
||||
|
||||
@@ -56,11 +56,9 @@ exports.startup = function() {
|
||||
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.close();
|
||||
srcDocument.title = windowTitle;
|
||||
$tw.eventBus.emit("window:opened",{windowID, window: srcWindow});
|
||||
srcWindow.addEventListener("beforeunload",function(event) {
|
||||
delete $tw.windows[windowID];
|
||||
$tw.wiki.removeEventListener("change",refreshHandler);
|
||||
$tw.eventBus.emit("window:closed",{windowID});
|
||||
},false);
|
||||
// Set up the styles
|
||||
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
|
||||
|
||||
@@ -47,16 +47,16 @@ ClassicStoryView.prototype.insert = function(widget) {
|
||||
// Reset the margin once the transition is over
|
||||
setTimeout(function() {
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{marginBottom: ""}
|
||||
]);
|
||||
$tw.utils.removeStyle(targetElement, "transition");
|
||||
},duration);
|
||||
// Set up the initial position of the element
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{marginBottom: (-currHeight) + "px"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
$tw.utils.removeStyle(targetElement, "transition");
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
// Transition to the final position
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
@@ -64,7 +64,7 @@ ClassicStoryView.prototype.insert = function(widget) {
|
||||
"margin-bottom " + duration + "ms " + easing},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,9 +94,11 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
setTimeout(removeElement,duration);
|
||||
// Animate the closure
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "translateX(0px)"},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opacity"]);
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
|
||||
@@ -111,4 +113,4 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.classic = ClassicStoryView;
|
||||
exports.classic = ClassicStoryView;
|
||||
|
||||
@@ -37,7 +37,10 @@ PopStoryView.prototype.insert = function(widget) {
|
||||
}
|
||||
// Reset once the transition is over
|
||||
setTimeout(function() {
|
||||
$tw.utils.removeStyles(targetElement, ["transition", "transform"]);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "none"}
|
||||
]);
|
||||
$tw.utils.setStyle(widget.document.body,[
|
||||
{"overflow-x": ""}
|
||||
]);
|
||||
@@ -48,10 +51,10 @@ PopStoryView.prototype.insert = function(widget) {
|
||||
]);
|
||||
// Set up the initial position of the element
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "scale(2)"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
$tw.utils.removeStyle(targetElement, "transition");
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
// Transition to the final position
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
@@ -60,9 +63,6 @@ PopStoryView.prototype.insert = function(widget) {
|
||||
{transform: "scale(1)"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
setTimeout(function() {
|
||||
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opactity"]);
|
||||
}, duration)
|
||||
};
|
||||
|
||||
PopStoryView.prototype.remove = function(widget) {
|
||||
@@ -81,7 +81,11 @@ PopStoryView.prototype.remove = function(widget) {
|
||||
// Remove the element at the end of the transition
|
||||
setTimeout(removeElement,duration);
|
||||
// Animate the closure
|
||||
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opacity"]);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "scale(1)"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
|
||||
@@ -91,4 +95,4 @@ PopStoryView.prototype.remove = function(widget) {
|
||||
]);
|
||||
};
|
||||
|
||||
exports.pop = PopStoryView;
|
||||
exports.pop = PopStoryView;
|
||||
|
||||
@@ -96,9 +96,6 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
|
||||
{transform: "translateX(0px) translateY(0px) scale(1)"},
|
||||
{zIndex: "500"},
|
||||
]);
|
||||
setTimeout(function() {
|
||||
$tw.utils.removeStyles(targetElement, ["transition", "opacity", "transform", "zIndex"]);
|
||||
}, duration);
|
||||
// Transform the previous tiddler out of the way and then hide it
|
||||
if(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {
|
||||
scale = zoomBounds.width / sourceBounds.width;
|
||||
@@ -210,9 +207,6 @@ ZoominListView.prototype.remove = function(widget) {
|
||||
{opacity: "0"},
|
||||
{zIndex: "0"}
|
||||
]);
|
||||
setTimeout(function() {
|
||||
$tw.utils.removeStyles(toWidgetDomNode, ["transformOrigin", "transform", "transition", "opacity", "zIndex"]);
|
||||
}, duration);
|
||||
setTimeout(removeElement,duration);
|
||||
// Now the tiddler we're going back to
|
||||
if(toWidgetDomNode) {
|
||||
@@ -228,4 +222,4 @@ ZoominListView.prototype.logTextNodeRoot = function(node) {
|
||||
this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent);
|
||||
};
|
||||
|
||||
exports.zoomin = ZoominListView;
|
||||
exports.zoomin = ZoominListView;
|
||||
|
||||
142
core/modules/utils/base64-utf8/base64-utf8.module.js
Normal file
142
core/modules/utils/base64-utf8/base64-utf8.module.js
Normal file
@@ -0,0 +1,142 @@
|
||||
// From https://gist.github.com/Nijikokun/5192472
|
||||
//
|
||||
// UTF8 Module
|
||||
//
|
||||
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
(function (name, definition, context, dependencies) {
|
||||
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
|
||||
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
|
||||
else { context[name] = definition.apply(context); }
|
||||
})('utf8', function () {
|
||||
return {
|
||||
encode: function (string) {
|
||||
if (typeof string !== 'string') return string;
|
||||
else string = string.replace(/\r\n/g, "\n");
|
||||
var output = "", i = 0, charCode;
|
||||
|
||||
for (i; i < string.length; i++) {
|
||||
charCode = string.charCodeAt(i);
|
||||
|
||||
if (charCode < 128) {
|
||||
output += String.fromCharCode(charCode);
|
||||
} else if ((charCode > 127) && (charCode < 2048)) {
|
||||
output += String.fromCharCode((charCode >> 6) | 192);
|
||||
output += String.fromCharCode((charCode & 63) | 128);
|
||||
} else if ((charCode > 55295) && (charCode < 57344) && string.length > i+1) {
|
||||
// Surrogate pair
|
||||
var hiSurrogate = charCode;
|
||||
var loSurrogate = string.charCodeAt(i+1);
|
||||
i++; // Skip the low surrogate on the next loop pass
|
||||
var codePoint = (((hiSurrogate - 55296) << 10) | (loSurrogate - 56320)) + 65536;
|
||||
output += String.fromCharCode((codePoint >> 18) | 240);
|
||||
output += String.fromCharCode(((codePoint >> 12) & 63) | 128);
|
||||
output += String.fromCharCode(((codePoint >> 6) & 63) | 128);
|
||||
output += String.fromCharCode((codePoint & 63) | 128);
|
||||
} else {
|
||||
// Not a surrogate pair, or a dangling surrogate without its partner that we'll just encode as-is
|
||||
output += String.fromCharCode((charCode >> 12) | 224);
|
||||
output += String.fromCharCode(((charCode >> 6) & 63) | 128);
|
||||
output += String.fromCharCode((charCode & 63) | 128);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
decode: function (string) {
|
||||
if (typeof string !== 'string') return string;
|
||||
var output = "", i = 0, charCode = 0;
|
||||
|
||||
while (i < string.length) {
|
||||
charCode = string.charCodeAt(i);
|
||||
|
||||
if (charCode < 128) {
|
||||
output += String.fromCharCode(charCode),
|
||||
i++;
|
||||
} else if ((charCode > 191) && (charCode < 224)) {
|
||||
output += String.fromCharCode(((charCode & 31) << 6) | (string.charCodeAt(i + 1) & 63));
|
||||
i += 2;
|
||||
} else if ((charCode > 223) && (charCode < 240)) {
|
||||
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63));
|
||||
i += 3;
|
||||
} else {
|
||||
var codePoint = ((charCode & 7) << 18) | ((string.charCodeAt(i + 1) & 63) << 12) | ((string.charCodeAt(i + 2) & 63) << 6) | (string.charCodeAt(i + 3) & 63);
|
||||
// output += String.fromCodePoint(codePoint); // Can't do this because Internet Explorer doesn't have String.fromCodePoint
|
||||
output += String.fromCharCode(((codePoint - 65536) >> 10) + 55296) + String.fromCharCode(((codePoint - 65536) & 1023) + 56320); // So we do this instead
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
}, this);
|
||||
|
||||
// Base64 Module
|
||||
//
|
||||
// Cleaner, modularized and properly scoped base64 encoding and decoding module for strings.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
(function (name, definition, context, dependencies) {
|
||||
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
|
||||
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
|
||||
else { context[name] = definition.apply(context); }
|
||||
})('base64', function (utf8) {
|
||||
var $this = this;
|
||||
var $utf8 = utf8 || this.utf8;
|
||||
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
return {
|
||||
encode: function (input) {
|
||||
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
|
||||
if (typeof input !== 'string') return input;
|
||||
else input = $utf8.encode(input);
|
||||
var output = "", a, b, c, d, e, f, g, i = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
a = input.charCodeAt(i++);
|
||||
b = input.charCodeAt(i++);
|
||||
c = input.charCodeAt(i++);
|
||||
d = a >> 2;
|
||||
e = ((a & 3) << 4) | (b >> 4);
|
||||
f = ((b & 15) << 2) | (c >> 6);
|
||||
g = c & 63;
|
||||
|
||||
if (isNaN(b)) f = g = 64;
|
||||
else if (isNaN(c)) g = 64;
|
||||
|
||||
output += map.charAt(d) + map.charAt(e) + map.charAt(f) + map.charAt(g);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
decode: function (input) {
|
||||
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
|
||||
if (typeof input !== 'string') return input;
|
||||
else input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
var output = "", a, b, c, d, e, f, g, i = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
d = map.indexOf(input.charAt(i++));
|
||||
e = map.indexOf(input.charAt(i++));
|
||||
f = map.indexOf(input.charAt(i++));
|
||||
g = map.indexOf(input.charAt(i++));
|
||||
|
||||
a = (d << 2) | (e >> 4);
|
||||
b = ((e & 15) << 4) | (f >> 2);
|
||||
c = ((f & 3) << 6) | g;
|
||||
|
||||
output += String.fromCharCode(a);
|
||||
if (f != 64) output += String.fromCharCode(b);
|
||||
if (g != 64) output += String.fromCharCode(c);
|
||||
}
|
||||
|
||||
return $utf8.decode(output);
|
||||
}
|
||||
}
|
||||
}, this, [ "utf8" ]);
|
||||
9
core/modules/utils/base64-utf8/base64-utf8.module.min.js
vendored
Normal file
9
core/modules/utils/base64-utf8/base64-utf8.module.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// From https://gist.github.com/Nijikokun/5192472
|
||||
//
|
||||
// UTF8 Module
|
||||
//
|
||||
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&"function"===o.define&&o.define.amd?define("utf8",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if("string"!=typeof r)return r;r=r.replace(/\r\n/g,"\n");for(var e,o="",t=0;t<r.length;t++)if((e=r.charCodeAt(t))<128)o+=String.fromCharCode(e);else if(e>127&&e<2048)o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128);else if(e>55295&&e<57344&&r.length>t+1){var i=e,n=r.charCodeAt(t+1);t++;var d=65536+(i-55296<<10|n-56320);o+=String.fromCharCode(d>>18|240),o+=String.fromCharCode(d>>12&63|128),o+=String.fromCharCode(d>>6&63|128),o+=String.fromCharCode(63&d|128)}else o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128);return o},decode:function(r){if("string"!=typeof r)return r;for(var e="",o=0,t=0;o<r.length;)if((t=r.charCodeAt(o))<128)e+=String.fromCharCode(t),o++;else if(t>191&&t<224)e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2;else if(t>223&&t<240)e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3;else{var i=(7&t)<<18|(63&r.charCodeAt(o+1))<<12|(63&r.charCodeAt(o+2))<<6|63&r.charCodeAt(o+3);e+=String.fromCharCode(55296+(i-65536>>10))+String.fromCharCode(56320+(i-65536&1023)),o+=4}return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var i=0;i<t.length;i++)o[t[i]]=o.require(t[i]);o.module.exports=e.apply(o)}else void 0!==o.define&&"function"===o.define&&o.define.amd?define("base64",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=e.encode(r);for(var t,i,n,d,f,a,h,C="",c=0;c<r.length;)d=(t=r.charCodeAt(c++))>>2,f=(3&t)<<4|(i=r.charCodeAt(c++))>>4,a=(15&i)<<2|(n=r.charCodeAt(c++))>>6,h=63&n,isNaN(i)?a=h=64:isNaN(n)&&(h=64),C+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return C},decode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var t,i,n,d,f,a,h="",C=0;C<r.length;)t=o.indexOf(r.charAt(C++))<<2|(d=o.indexOf(r.charAt(C++)))>>4,i=(15&d)<<4|(f=o.indexOf(r.charAt(C++)))>>2,n=(3&f)<<6|(a=o.indexOf(r.charAt(C++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(i)),64!=a&&(h+=String.fromCharCode(n));return e.decode(h)}}},this,["utf8"]);
|
||||
14
core/modules/utils/base64-utf8/tiddlywiki.files
Normal file
14
core/modules/utils/base64-utf8/tiddlywiki.files
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "base64-utf8.module.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/core/modules/utils/base64-utf8/base64-utf8.module.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "(function(){",
|
||||
"suffix": "}).call(exports);"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -24,26 +24,6 @@ exports.setStyle = function(element,styles) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Remove style properties of an element
|
||||
element: dom node
|
||||
styleProperties: ordered array of string property names
|
||||
*/
|
||||
exports.removeStyles = function(element, styleProperties) {
|
||||
for (var i=0; i<styleProperties.length; i++) {
|
||||
element.style.removeProperty($tw.utils.convertStyleNameToPropertyName(styleProperties[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Remove single style property of an element
|
||||
element: dom node
|
||||
styleProperty: string property name
|
||||
*/
|
||||
exports.removeStyle = function(element, styleProperty) {
|
||||
$tw.utils.removeStyles(element, [styleProperty])
|
||||
}
|
||||
|
||||
/*
|
||||
Converts a standard CSS property name into the local browser-specific equivalent. For example:
|
||||
"background-color" --> "backgroundColor"
|
||||
|
||||
@@ -210,7 +210,7 @@ Modal.prototype.display = function(title,options) {
|
||||
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
|
||||
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true" || tiddler.fields["mask-closable"] === "" || "mask-closable" in tiddler.fields === false)) {
|
||||
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true")) {
|
||||
modalBackdrop.addEventListener("click",closeHandler,false);
|
||||
}
|
||||
// Set the initial styles for the message
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/messaging.js
|
||||
type: application/javascript
|
||||
module-type: utils-browser
|
||||
|
||||
Messaging utilities for use with window.postMessage() etc.
|
||||
|
||||
This module intentionally has no dependencies so that it can be included in non-TiddlyWiki projects
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var RESPONSE_TIMEOUT = 2 * 1000;
|
||||
|
||||
/*
|
||||
Class to handle subscribing to publishers
|
||||
|
||||
target: Target window (eg iframe.contentWindow)
|
||||
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||
onsubscribe: Function to be invoked with err parameter when the subscription is established, or there is a timeout
|
||||
onmessage: Function to be invoked when a new message arrives, invoked with (data,callback). The callback is invoked with the argument (response)
|
||||
*/
|
||||
function BrowserMessagingSubscriber(options) {
|
||||
var self = this;
|
||||
this.target = options.target;
|
||||
this.type = options.type;
|
||||
this.onsubscribe = options.onsubscribe || function() {};
|
||||
this.onmessage = options.onmessage;
|
||||
this.hasConfirmed = false;
|
||||
this.channel = new MessageChannel();
|
||||
this.channel.port1.addEventListener("message",function(event) {
|
||||
if(this.timerID) {
|
||||
clearTimeout(this.timerID);
|
||||
this.timerID = null;
|
||||
}
|
||||
if(event.data) {
|
||||
if(event.data.verb === "SUBSCRIBED") {
|
||||
self.hasConfirmed = true;
|
||||
self.onsubscribe(null);
|
||||
} else if(event.data.verb === self.type) {
|
||||
self.onmessage(event.data,function(response) {
|
||||
// Send the response back on the supplied port, and then close it
|
||||
event.ports[0].postMessage(response);
|
||||
event.ports[0].close();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set a timer so that if we don't hear from the iframe before a timeout we alert the user
|
||||
this.timerID = setTimeout(function() {
|
||||
if(!self.hasConfirmed) {
|
||||
self.onsubscribe("NO_RESPONSE");
|
||||
}
|
||||
},RESPONSE_TIMEOUT);
|
||||
this.channel.port1.start();
|
||||
this.target.postMessage({verb: "SUBSCRIBE",to: self.type},"*",[this.channel.port2]);
|
||||
}
|
||||
|
||||
exports.BrowserMessagingSubscriber = BrowserMessagingSubscriber;
|
||||
|
||||
/*
|
||||
Class to handle publishing subscriptions
|
||||
|
||||
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||
onsubscribe: Function to be invoked when a subscription occurs
|
||||
*/
|
||||
function BrowserMessagingPublisher(options) {
|
||||
var self = this;
|
||||
this.type = options.type;
|
||||
this.hostIsListening = false;
|
||||
this.port = null;
|
||||
// Listen to connection requests from the host
|
||||
window.addEventListener("message",function(event) {
|
||||
if(event.data && event.data.verb === "SUBSCRIBE" && event.data.to === self.type) {
|
||||
self.hostIsListening = true;
|
||||
// Acknowledge
|
||||
self.port = event.ports[0];
|
||||
self.port.postMessage({verb: "SUBSCRIBED", to: self.type});
|
||||
if(options.onsubscribe) {
|
||||
options.onsubscribe(event.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BrowserMessagingPublisher.prototype.canSend = function() {
|
||||
return !!this.hostIsListening && !!this.port;
|
||||
};
|
||||
|
||||
BrowserMessagingPublisher.prototype.send = function(data,callback) {
|
||||
var self = this;
|
||||
callback = callback || function() {};
|
||||
// Check that we've been initialised by the host
|
||||
if(!this.hostIsListening || !this.port) {
|
||||
return false;
|
||||
}
|
||||
// Create a channel for the confirmation
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.addEventListener("message",function(event) {
|
||||
if(event.data && event.data.verb === "OK") {
|
||||
callback(null);
|
||||
} else {
|
||||
callback("BrowserMessagingPublisher for " + self.type + " error: " + (event.data || {}).verb);
|
||||
}
|
||||
channel.port1.close();
|
||||
});
|
||||
channel.port1.start();
|
||||
// Send the save request with the port for the response
|
||||
this.port.postMessage(data,[channel.port2]);
|
||||
};
|
||||
|
||||
BrowserMessagingPublisher.prototype.close = function() {
|
||||
if(this.port) {
|
||||
this.port.close();
|
||||
this.hostIsListening = false;
|
||||
this.port = null;
|
||||
}
|
||||
};
|
||||
|
||||
exports.BrowserMessagingPublisher = BrowserMessagingPublisher;
|
||||
|
||||
})();
|
||||
@@ -9,6 +9,8 @@ Various static utility functions.
|
||||
|
||||
"use strict";
|
||||
|
||||
var base64utf8 = require("$:/core/modules/utils/base64-utf8/base64-utf8.module.js");
|
||||
|
||||
/*
|
||||
Display a message, in colour if we're on a terminal
|
||||
*/
|
||||
@@ -840,50 +842,22 @@ if(typeof window !== 'undefined') {
|
||||
}
|
||||
}
|
||||
|
||||
exports.base64ToBytes = function(base64) {
|
||||
const binString = exports.atob(base64);
|
||||
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
||||
};
|
||||
|
||||
exports.bytesToBase64 = function(bytes) {
|
||||
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
||||
return exports.btoa(binString);
|
||||
};
|
||||
|
||||
exports.base64EncodeUtf8 = function(str) {
|
||||
if ($tw.browser) {
|
||||
return exports.bytesToBase64(new TextEncoder().encode(str));
|
||||
} else {
|
||||
const buff = Buffer.from(str, "utf-8");
|
||||
return buff.toString("base64");
|
||||
}
|
||||
};
|
||||
|
||||
exports.base64DecodeUtf8 = function(str) {
|
||||
if ($tw.browser) {
|
||||
return new TextDecoder().decode(exports.base64ToBytes(str));
|
||||
} else {
|
||||
const buff = Buffer.from(str, "base64");
|
||||
return buff.toString("utf-8");
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Decode a base64 string
|
||||
*/
|
||||
exports.base64Decode = function(string64,binary,urlsafe) {
|
||||
const encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
|
||||
var encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
|
||||
if(binary) return exports.atob(encoded)
|
||||
else return exports.base64DecodeUtf8(encoded);
|
||||
else return base64utf8.base64.decode.call(base64utf8,encoded);
|
||||
};
|
||||
|
||||
/*
|
||||
Encode a string to base64
|
||||
*/
|
||||
exports.base64Encode = function(string64,binary,urlsafe) {
|
||||
let encoded;
|
||||
var encoded;
|
||||
if(binary) encoded = exports.btoa(string64);
|
||||
else encoded = exports.base64EncodeUtf8(string64);
|
||||
else encoded = base64utf8.base64.encode.call(base64utf8,string64);
|
||||
if(urlsafe) {
|
||||
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
|
||||
}
|
||||
@@ -1049,7 +1023,7 @@ exports.makeCompareFunction = function(type,options) {
|
||||
return compare(dateA,dateB);
|
||||
},
|
||||
"version": function(a,b) {
|
||||
return compare($tw.utils.compareVersions(a,b),0);
|
||||
return $tw.utils.compareVersions(a,b);
|
||||
},
|
||||
"alphanumeric": function(a,b) {
|
||||
if(!isCaseSensitive) {
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/audio.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Basic Audio widget for displaying audio files.
|
||||
This is a simple implementation that can be overridden by plugins
|
||||
for more advanced functionality.
|
||||
|
||||
\*/
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var AudioWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
AudioWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
AudioWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
|
||||
// Create audio element
|
||||
var audioElement = this.document.createElement("audio");
|
||||
audioElement.setAttribute("controls", this.getAttribute("controls", "controls"));
|
||||
audioElement.setAttribute("style", this.getAttribute("style", "width: 100%; object-fit: contain"));
|
||||
audioElement.className = "tw-audio-element";
|
||||
|
||||
// Set source
|
||||
if(this.audioSource) {
|
||||
if (this.audioSource.indexOf("data:") === 0) {
|
||||
audioElement.setAttribute("src", this.audioSource);
|
||||
} else {
|
||||
var sourceElement = this.document.createElement("source");
|
||||
sourceElement.setAttribute("src", this.audioSource);
|
||||
if(this.audioType) {
|
||||
sourceElement.setAttribute("type", this.audioType);
|
||||
}
|
||||
audioElement.appendChild(sourceElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the audio into the DOM
|
||||
parent.insertBefore(audioElement, nextSibling);
|
||||
this.domNodes.push(audioElement);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
AudioWidget.prototype.execute = function() {
|
||||
// Get the audio source and type
|
||||
this.audioSource = this.getAttribute("src");
|
||||
this.audioType = this.getAttribute("type");
|
||||
this.audioControls = this.getAttribute("controls", "controls");
|
||||
|
||||
// Try to get from tiddler attribute
|
||||
if(!this.audioSource && this.getAttribute("tiddler")) {
|
||||
var tiddlerTitle = this.getAttribute("tiddler");
|
||||
var tiddler = this.wiki.getTiddler(tiddlerTitle);
|
||||
if(tiddler) {
|
||||
if(tiddler.fields._canonical_uri) {
|
||||
this.audioSource = tiddler.fields._canonical_uri;
|
||||
this.audioType = tiddler.fields.type;
|
||||
} else if(tiddler.fields.text) {
|
||||
this.audioSource = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
|
||||
this.audioType = tiddler.fields.type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we have a tiddler for saving timestamps
|
||||
this.tiddlerTitle = this.getAttribute("tiddler");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
AudioWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.src || changedAttributes.type || changedAttributes.controls || changedAttributes.tiddler) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
exports.audio = AudioWidget;
|
||||
|
||||
|
||||
@@ -61,10 +61,6 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
||||
sourcePrefix: "data-",
|
||||
destPrefix: "data-"
|
||||
});
|
||||
this.assignAttributes(domNode,{
|
||||
sourcePrefix: "aria-",
|
||||
destPrefix: "aria-"
|
||||
});
|
||||
// Assign other attributes
|
||||
if(this.style) {
|
||||
domNode.setAttribute("style",this.style);
|
||||
@@ -72,6 +68,9 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
||||
if(this.tooltip) {
|
||||
domNode.setAttribute("title",this.tooltip);
|
||||
}
|
||||
if(this["aria-label"]) {
|
||||
domNode.setAttribute("aria-label",this["aria-label"]);
|
||||
}
|
||||
if (this.role) {
|
||||
domNode.setAttribute("role", this.role);
|
||||
}
|
||||
@@ -216,6 +215,7 @@ ButtonWidget.prototype.execute = function() {
|
||||
this.setTo = this.getAttribute("setTo");
|
||||
this.popup = this.getAttribute("popup");
|
||||
this.hover = this.getAttribute("hover");
|
||||
this["aria-label"] = this.getAttribute("aria-label");
|
||||
this.role = this.getAttribute("role");
|
||||
this.tooltip = this.getAttribute("tooltip");
|
||||
this.style = this.getAttribute("style");
|
||||
@@ -271,10 +271,6 @@ ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||
sourcePrefix: "data-",
|
||||
destPrefix: "data-"
|
||||
});
|
||||
this.assignAttributes(this.domNodes[0],{
|
||||
sourcePrefix: "aria-",
|
||||
destPrefix: "aria-"
|
||||
});
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
};
|
||||
|
||||
@@ -74,8 +74,6 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Create the DOM node and render children
|
||||
var domNode = this.document.createElementNS(this.namespace,this.tag);
|
||||
this.assignAttributes(domNode,{excludeEventAttributes: true});
|
||||
// Allow hooks to manipulate the DOM node. Eg: Add debug info
|
||||
$tw.hooks.invokeHook("th-dom-rendering-element", domNode, this);
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.renderChildren(domNode,null);
|
||||
this.domNodes.push(domNode);
|
||||
|
||||
@@ -44,7 +44,7 @@ EventWidget.prototype.render = function(parent,nextSibling) {
|
||||
domNode.addEventListener(type,function(event) {
|
||||
var selector = self.getAttribute("selector"),
|
||||
matchSelector = self.getAttribute("matchSelector"),
|
||||
actions = self.getAttribute("$"+type),
|
||||
actions = self.getAttribute("$"+type) || self.getAttribute("actions-"+type),
|
||||
stopPropagation = self.getAttribute("stopPropagation","onaction"),
|
||||
selectedNode = event.target,
|
||||
selectedNodeRect,
|
||||
@@ -122,6 +122,9 @@ EventWidget.prototype.execute = function() {
|
||||
self.types.push(key.slice(1));
|
||||
}
|
||||
});
|
||||
if(!this.types.length) {
|
||||
this.types = this.getAttribute("events","").split(" ");
|
||||
}
|
||||
this.elementTag = this.getAttribute("tag");
|
||||
// Make child widgets
|
||||
this.makeChildWidgets();
|
||||
|
||||
@@ -45,10 +45,6 @@ LinkWidget.prototype.render = function(parent,nextSibling) {
|
||||
sourcePrefix: "data-",
|
||||
destPrefix: "data-"
|
||||
});
|
||||
this.assignAttributes(domNode,{
|
||||
sourcePrefix: "aria-",
|
||||
destPrefix: "aria-"
|
||||
});
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.renderChildren(domNode,null);
|
||||
this.domNodes.push(domNode);
|
||||
@@ -129,13 +125,9 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
||||
});
|
||||
domNode.setAttribute("title",tooltipText);
|
||||
}
|
||||
if(this.role) {
|
||||
domNode.setAttribute("role",this.role);
|
||||
if(this["aria-label"]) {
|
||||
domNode.setAttribute("aria-label",this["aria-label"]);
|
||||
}
|
||||
this.assignAttributes(domNode,{
|
||||
sourcePrefix: "aria-",
|
||||
destPrefix: "aria-"
|
||||
})
|
||||
// Add a click event handler
|
||||
$tw.utils.addEventListeners(domNode,[
|
||||
{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"},
|
||||
@@ -147,8 +139,6 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
||||
dragTiddlerFn: function() {return self.to;},
|
||||
widget: this
|
||||
});
|
||||
} else if(this.draggable === "no") {
|
||||
domNode.setAttribute("draggable","false");
|
||||
}
|
||||
// Assign data- attributes
|
||||
this.assignAttributes(domNode,{
|
||||
@@ -198,7 +188,7 @@ LinkWidget.prototype.execute = function() {
|
||||
// Pick up our attributes
|
||||
this.to = this.getAttribute("to",this.getVariable("currentTiddler"));
|
||||
this.tooltip = this.getAttribute("tooltip");
|
||||
this.role = this.getAttribute("role");
|
||||
this["aria-label"] = this.getAttribute("aria-label");
|
||||
this.linkClasses = this.getAttribute("class");
|
||||
this.overrideClasses = this.getAttribute("overrideClass");
|
||||
this.tabIndex = this.getAttribute("tabindex");
|
||||
|
||||
@@ -94,6 +94,8 @@ RangeWidget.prototype.getActionVariables = function(options) {
|
||||
|
||||
// actionsStart
|
||||
RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
||||
this.mouseDown = true; // TODO remove once IE is gone.
|
||||
this.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone!
|
||||
this.handleEvent(event);
|
||||
// Trigger actions
|
||||
if(this.actionsMouseDown) {
|
||||
@@ -104,16 +106,26 @@ RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
||||
|
||||
// actionsStop
|
||||
RangeWidget.prototype.handleMouseUpEvent = function(event) {
|
||||
this.mouseDown = false; // TODO remove once IE is gone.
|
||||
this.handleEvent(event);
|
||||
// Trigger actions
|
||||
if(this.actionsMouseUp) {
|
||||
var variables = this.getActionVariables()
|
||||
this.invokeActionString(this.actionsMouseUp,this,event,variables);
|
||||
}
|
||||
// TODO remove the following if() once IE is gone!
|
||||
if ($tw.browser.isIE) {
|
||||
if (this.startValue !== this.inputDomNode.value) {
|
||||
this.handleChangeEvent(event);
|
||||
this.startValue = this.inputDomNode.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RangeWidget.prototype.handleChangeEvent = function(event) {
|
||||
this.handleInputEvent(event);
|
||||
if (this.mouseDown) { // TODO refactor this function once IE is gone.
|
||||
this.handleInputEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
RangeWidget.prototype.handleInputEvent = function(event) {
|
||||
@@ -140,6 +152,8 @@ RangeWidget.prototype.handleEvent = function(event) {
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
RangeWidget.prototype.execute = function() {
|
||||
// TODO remove the next 1 lines once IE is gone!
|
||||
this.mouseUp = true; // Needed for IE10
|
||||
// Get the parameters from the attributes
|
||||
this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||
this.tiddlerField = this.getAttribute("field","text");
|
||||
|
||||
@@ -181,7 +181,7 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) {
|
||||
};
|
||||
|
||||
ScrollableWidget.prototype.listenerFunction = function(event) {
|
||||
var self = this;
|
||||
self = this;
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(function() {
|
||||
var existingTiddler = self.wiki.getTiddler(self.scrollableBind),
|
||||
|
||||
@@ -1443,7 +1443,7 @@ exports.search = function(text,options) {
|
||||
// Don't search the text field if the content type is binary
|
||||
var fieldName = searchFields[fieldIndex];
|
||||
if(fieldName === "text" && contentTypeInfo.encoding !== "utf8") {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
var str = tiddler.fields[fieldName],
|
||||
t;
|
||||
|
||||
@@ -47,7 +47,6 @@ modal-footer-background: #f5f5f5
|
||||
modal-footer-border: #dddddd
|
||||
modal-header-border: #eeeeee
|
||||
muted-foreground: #bbb
|
||||
network-activity-foreground: <<colour primary>>
|
||||
notification-background: #ffffdd
|
||||
notification-border: #999999
|
||||
page-background: #6f6f70
|
||||
@@ -57,26 +56,22 @@ primary: #29a6ee
|
||||
select-tag-background:
|
||||
select-tag-foreground:
|
||||
sidebar-button-foreground: <<colour foreground>>
|
||||
sidebar-controls-foreground-hover: #222222
|
||||
sidebar-controls-foreground-hover: #000000
|
||||
sidebar-controls-foreground: #c2c1c2
|
||||
sidebar-foreground-shadow: transparent
|
||||
sidebar-foreground-shadow: rgba(255,255,255,0)
|
||||
sidebar-foreground: #d3d2d4
|
||||
sidebar-muted-foreground-hover: #333333
|
||||
sidebar-muted-foreground-hover: #444444
|
||||
sidebar-muted-foreground: #c0c0c0
|
||||
sidebar-tab-background-selected: #6f6f70
|
||||
sidebar-tab-background: #666667
|
||||
sidebar-tab-border-selected: #999
|
||||
sidebar-tab-border: #515151
|
||||
sidebar-tab-divider: #999
|
||||
sidebar-tab-foreground-selected: #bfbfbf
|
||||
sidebar-tab-foreground: #b0b0b0
|
||||
sidebar-tab-foreground-selected:
|
||||
sidebar-tab-foreground: #999
|
||||
sidebar-tiddler-link-foreground-hover: #444444
|
||||
sidebar-tiddler-link-foreground: #aaaaaa
|
||||
sidebar-tiddler-link-foreground: #d1d0d2
|
||||
site-title-foreground: <<colour tiddler-title-foreground>>
|
||||
stability-deprecated: #bf616a
|
||||
stability-experimental: #d08770
|
||||
stability-legacy: #88c0d0
|
||||
stability-stable: #a3be8c
|
||||
static-alert-foreground: #aaaaaa
|
||||
tab-background-selected: #ffffff
|
||||
tab-background: #d8d8d8
|
||||
|
||||
@@ -3,7 +3,7 @@ title: $:/core/save/all-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
|
||||
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
|
||||
|
||||
@@ -3,7 +3,7 @@ title: $:/core/save/offline-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
title: $:/core/templates/tiddlywiki5-external-js.html
|
||||
|
||||
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
|
||||
<$set name="rawMarkupFilter" filter="[enlist<saveTiddlerAndShadowsFilter>] +[[$:/core]plugintiddlers[]]">
|
||||
`<!doctype html>
|
||||
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<!--~~ Raw markup for the top of the head section ~~-->
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
|
||||
<meta name="application-name" content="TiddlyWiki" />
|
||||
<meta name="generator" content="TiddlyWiki" />
|
||||
@@ -23,13 +22,13 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
||||
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
|
||||
|
||||
<!--~~ Raw markup ~~-->
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
</head>
|
||||
<body class="tc-body">
|
||||
<!--~~ Raw markup for the top of the body section ~~-->
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
<!--~~ Static styles ~~-->
|
||||
<div id="styleArea">
|
||||
`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`
|
||||
@@ -43,10 +42,9 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
||||
<!--~~ Ordinary tiddlers ~~-->
|
||||
`{{$:/core/templates/store.area.template.html}}`
|
||||
<!--~~ Raw markup for the bottom of the body section ~~-->
|
||||
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
<!--~~ Load external JavaScripts ~~-->
|
||||
<script src="`{{{ [<coreURL>] }}}`" onerror="alert('Error: Cannot load `{{{ [<coreURL>] }}}`');"></script>
|
||||
</body>
|
||||
</html>`
|
||||
</$set>
|
||||
</$set>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user