mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-23 19:34:39 +00:00
Compare commits
31 Commits
new-releas
...
tiddlywiki
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efe58e41bc | ||
|
|
79e3d14698 | ||
|
|
763d717a13 | ||
|
|
419fe68ee2 | ||
|
|
47ab3476f6 | ||
|
|
f0e64660f2 | ||
|
|
7cb422242a | ||
|
|
5fa1098c03 | ||
|
|
92dc927c7b | ||
|
|
f3fa69e229 | ||
|
|
7fb8560908 | ||
|
|
ff7814360e | ||
|
|
2d9303c6ff | ||
|
|
6aee5eb0c7 | ||
|
|
4196d96adc | ||
|
|
838fad916d | ||
|
|
935e89bd93 | ||
|
|
ecba671bcf | ||
|
|
4b824795c8 | ||
|
|
fc74219c0b | ||
|
|
ffde2da16c | ||
|
|
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;
|
||||
|
||||
14
community/people/ChristianByron.tid
Normal file
14
community/people/ChristianByron.tid
Normal file
@@ -0,0 +1,14 @@
|
||||
title: @Christian_Byron
|
||||
tags: Community/Person
|
||||
fullname: Christian Byron
|
||||
talk.tiddlywiki.org: Christian_Byron
|
||||
github: ceebeetree
|
||||
linkedin: www.linkedin.com/in/christian-byron-b84a594/
|
||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEBAAMBAAAAAAAAAAAAAAAHBgEDBQQBAAMBAAAAAAAAAAAAAAAAAAABAwX/2gAMAwEAAhADEAAAADv2xtJlY03sqePW3ARS1RSydIhcH//EACcQAAICAgIBAgYDAAAAAAAAAAECAwQFEQASMRMhBhBBk8HRIzJx/9oACAEBAAE/AMFQxs+NExqJLMCwYE+SOT4bF3qr+hAIpRsDQ6lWH0Yco4S/eVniRVQHXZzrZ5dwGQpQtNII2RfJVvHMRl5cbKxC94n/ALp+RxfiKpNcgMMUqPIwjcnWip/I5XtUowaL3Ujir/xt79Glb6/4OZ7MV5oEpUzuIa7MPB14A5jpoYLsEsydo1bbLre+CWEEEYab7Uf74ZYSSThpvtR/vmRmhnuzywp1jZtquta+VPM49qlcy24lf017At7g8uZnHrUsGK3Ez+m3UBvcnXy//8QAHhEAAgEFAAMAAAAAAAAAAAAAAQIDAAQRIkEyUaH/2gAIAQIBAT8AmiuVlZkLEeQOflJPcvMAF0z65V+h0YIW52rBDuxUrztf/8QAIxEBAAEDAwMFAAAAAAAAAAAAAgEAAxEEBSMSQcEiMVJxof/aAAgBAwEBPwC/Z1ZvNBOYz1Gc/lDUat3ySPRM/H2P3W4hcbIldpxnxW3BcjQk9oznzX//2Q==
|
||||
|
||||
Hello ~TiddlyWikiers - I have been a long time fan, recent contributor to the TW community.
|
||||
Recently I have volunteered to run the [[TiddlyWiki Newsletter|https://tiddlywiki.substack.com/]] to spread the great news about TW.
|
||||
|
||||
I have been in the IT industry for about thirty years, mostly as a consultant and technical arcitect.
|
||||
More recently I went back to study a masters in IT focussing on AI and data science.
|
||||
Now my partner and I have started our own business ([[Sphere Innovations|https://sphere-innovations.com.au]]) - in consulting and building web applications for small to medium size businesses here in Australia.
|
||||
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
|
||||
@@ -1,6 +0,0 @@
|
||||
title: Newsletter Team
|
||||
tags: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
|
||||
The Newsletter Team is responsible for producing the TiddlyWiki Newsletter, a monthly email newsletter that highlights news, updates, and community contributions related to TiddlyWiki.
|
||||
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.
|
||||
|
||||
15
community/project/teams/TiddlyWiki Newsletter Team.tid
Normal file
15
community/project/teams/TiddlyWiki Newsletter Team.tid
Normal file
@@ -0,0 +1,15 @@
|
||||
title: TiddlyWiki Newsletter Team
|
||||
tags: Community/Team
|
||||
modified: 20251219090709874
|
||||
created: 20250909171928024
|
||||
leader: @Christian_Byron
|
||||
|
||||
The Newsletter Team is responsible for producing the [[TiddlyWiki Newsletter]]. We would love to have your help if you would like to get involved.
|
||||
|
||||
! Audience
|
||||
|
||||
The newsletter is intended for TiddlyWiki end users who do not track all the discussions on https://talk.tiddlywiki.org/.
|
||||
|
||||
Coverage of developer topics such as JavaScript and intricate wikitext should be handled thoughtfully to avoid alienating the core audience of end users.
|
||||
|
||||
Subscribing to the newsletter is intended to give people confidence that they will not miss any important developments.
|
||||
@@ -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
|
||||
|
||||
@@ -16,8 +16,12 @@ exports.json = function(source,operand,options) {
|
||||
spaces = /^\d+$/.test(operand) ? parseInt(operand,10) : operand;
|
||||
}
|
||||
source(function(tiddler,title) {
|
||||
var data = $tw.utils.parseJSONSafe(title,function(){return undefined;});
|
||||
|
||||
var data = $tw.utils.parseJSONSafe(title);
|
||||
try {
|
||||
data = JSON.parse(title);
|
||||
} catch(e) {
|
||||
data = undefined;
|
||||
}
|
||||
if(data !== undefined) {
|
||||
results.push(JSON.stringify(data,null,spaces));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,7 +22,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
|
||||
"use strict";
|
||||
|
||||
exports.name = "commentblock";
|
||||
exports.types = {block: true, pragma: true};
|
||||
exports.types = {block:true, pragma:true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
@@ -43,18 +43,9 @@ exports.findNextMatch = function(startPos) {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.endMatchRegExp.lastIndex;
|
||||
// Return a node representing the comment that is not rendered
|
||||
var commentStart = this.match.index;
|
||||
var commentEnd = this.endMatch.index + this.endMatch[0].length;
|
||||
return [{
|
||||
type: "void",
|
||||
children: [],
|
||||
text: this.parser.source.slice(commentStart, commentEnd),
|
||||
start: commentStart,
|
||||
end: commentEnd
|
||||
}];
|
||||
// Don't return any elements
|
||||
return [];
|
||||
};
|
||||
|
||||
@@ -40,13 +40,6 @@ exports.findNextMatch = function(startPos) {
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.endMatchRegExp.lastIndex;
|
||||
// Return a node representing the inline comment
|
||||
var commentStart = this.match.index;
|
||||
var commentEnd = this.endMatch.index + this.endMatch[0].length;
|
||||
return [{
|
||||
type: "void",
|
||||
text: this.parser.source.slice(commentStart, commentEnd),
|
||||
start: commentStart,
|
||||
end: commentEnd
|
||||
}];
|
||||
// Don't return any elements
|
||||
return [];
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ exports.parse = function() {
|
||||
// Return the classed span
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "s",
|
||||
tag: "strike",
|
||||
children: tree
|
||||
}];
|
||||
};
|
||||
|
||||
@@ -28,11 +28,11 @@ exports.init = function(parser) {
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
var start = this.parser.pos;
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Create the link unless it is suppressed
|
||||
if(this.match[0].substr(0,1) === "~") {
|
||||
return [{type: "text", text: this.match[0].substr(1), start: start, end: this.parser.pos}];
|
||||
return [{type: "text", text: this.match[0].substr(1)}];
|
||||
} else {
|
||||
return [{
|
||||
type: "element",
|
||||
|
||||
@@ -6,15 +6,15 @@ module-type: wikirule
|
||||
Wiki pragma rule for function, procedure and widget definitions
|
||||
|
||||
```
|
||||
\function name(param:"defaultvalue", param2:"defaultvalue")
|
||||
\function name(param:defaultvalue,param2:defaultvalue)
|
||||
definition text
|
||||
\end
|
||||
|
||||
\procedure name(param:"defaultvalue", param2:"defaultvalue")
|
||||
\procedure name(param:defaultvalue,param2:defaultvalue)
|
||||
definition text
|
||||
\end
|
||||
|
||||
\widget $mywidget(param:"defaultvalue", param2:"defaultvalue")
|
||||
\widget $mywidget(param:defaultvalue,param2:defaultvalue)
|
||||
definition text
|
||||
\end
|
||||
```
|
||||
|
||||
@@ -50,8 +50,6 @@ exports.parse = function() {
|
||||
}
|
||||
}
|
||||
} while(match && !match[1]);
|
||||
// Mark first and last node, and return the nodes
|
||||
if(tree[0]) tree[0].isRuleStart = true;
|
||||
if(tree[tree.length-1]) tree[tree.length-1].isRuleEnd = true;
|
||||
// Return the nodes
|
||||
return tree;
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ Parse the most recent match
|
||||
exports.parse = function() {
|
||||
// Retrieve the most recent match so that recursive calls don't overwrite it
|
||||
var tag = this.nextTag;
|
||||
if(!tag.isSelfClosing) {
|
||||
if (!tag.isSelfClosing) {
|
||||
tag.openTagStart = tag.start;
|
||||
tag.openTagEnd = tag.end;
|
||||
}
|
||||
@@ -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
|
||||
@@ -63,22 +63,22 @@ exports.parse = function() {
|
||||
}
|
||||
tag.end = this.parser.pos;
|
||||
tag.closeTagEnd = tag.end;
|
||||
if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== ">") {
|
||||
if (tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') {
|
||||
tag.closeTagStart = tag.end;
|
||||
} else {
|
||||
tag.closeTagStart = tag.closeTagEnd - 2;
|
||||
var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd;
|
||||
if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
|
||||
while(tag.closeTagStart >= closeTagMinPos) {
|
||||
if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
|
||||
while (tag.closeTagStart >= closeTagMinPos) {
|
||||
var char = this.parser.source[tag.closeTagStart];
|
||||
if(char === ">") {
|
||||
if (char === '>') {
|
||||
tag.closeTagStart = -1;
|
||||
break;
|
||||
}
|
||||
if(char === "<") break;
|
||||
if (char === '<') break;
|
||||
tag.closeTagStart -= 1;
|
||||
}
|
||||
if(tag.closeTagStart < closeTagMinPos) {
|
||||
if (tag.closeTagStart < closeTagMinPos) {
|
||||
tag.closeTagStart = tag.end;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ var listTypes = {
|
||||
":": {listTag: "dl", itemTag: "dd"},
|
||||
">": {listTag: "blockquote", itemTag: "div"}
|
||||
};
|
||||
exports.listTypes = listTypes;
|
||||
|
||||
/*
|
||||
Parse the most recent match
|
||||
|
||||
@@ -29,7 +29,7 @@ exports.findNextMatch = function(startPos) {
|
||||
var c = this.parser.source.charAt(nextCall.end);
|
||||
// Ensure EOL after parsed macro
|
||||
// If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym
|
||||
if((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
|
||||
if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
|
||||
this.nextCall = nextCall;
|
||||
return nextStart;
|
||||
}
|
||||
|
||||
@@ -42,5 +42,3 @@ exports.parse = function() {
|
||||
this.parser.pos = call.end;
|
||||
return [call];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -52,10 +52,9 @@ exports.parse = function() {
|
||||
}
|
||||
}
|
||||
// Is the remainder of the \define line blank after the parameter close paren?
|
||||
var reEnd,isBlock = true;
|
||||
var reEnd;
|
||||
if(this.match[3]) {
|
||||
// If so, it is a multiline definition and the end of the body is marked with \end
|
||||
isBlock = false;
|
||||
reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?\\s*?(?:$|\\r?\\n))","mg");
|
||||
} else {
|
||||
// Otherwise, the end of the definition is marked by the end of the line
|
||||
@@ -80,8 +79,7 @@ exports.parse = function() {
|
||||
attributes: {},
|
||||
children: [],
|
||||
params: params,
|
||||
isMacroDefinition: true,
|
||||
isBlock: isBlock && !!endMatch
|
||||
isMacroDefinition: true
|
||||
}];
|
||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]);
|
||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
|
||||
|
||||
@@ -31,7 +31,6 @@ Parse the most recent match
|
||||
*/
|
||||
exports.parse = function() {
|
||||
// Move past the pragma invocation
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Parse whitespace delimited tokens terminated by a line break
|
||||
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
|
||||
@@ -59,11 +58,6 @@ exports.parse = function() {
|
||||
this.parser.parseAsInline = true;
|
||||
}
|
||||
}
|
||||
return [{
|
||||
type: "void",
|
||||
children: [],
|
||||
parseAsInline: this.parser.parseAsInline,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}];
|
||||
// No parse tree nodes to return
|
||||
return [];
|
||||
};
|
||||
|
||||
@@ -113,5 +113,3 @@ exports.parseLink = function(source,pos) {
|
||||
node.end = closePos + 2;
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ exports.parse = function() {
|
||||
var text = this.match[1],
|
||||
link = this.match[2] || text,
|
||||
textEndPos = this.parser.source.indexOf("|", start);
|
||||
if(textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
|
||||
if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
|
||||
textEndPos = this.matchRegExp.lastIndex - 2;
|
||||
}
|
||||
var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start;
|
||||
|
||||
@@ -54,13 +54,6 @@ exports.parse = function() {
|
||||
if(tokens.length > 0) {
|
||||
this.parser.amendRules(tokens[0],tokens.slice(1));
|
||||
}
|
||||
// No widget to render, return void node.
|
||||
return [{
|
||||
type: "void",
|
||||
attributes: {
|
||||
action: {type: "string", value: tokens[0]},
|
||||
rules: {type: "string", value: tokens.slice(1).join(" ")}
|
||||
},
|
||||
children: []
|
||||
}];
|
||||
// No parse tree nodes to return
|
||||
return [];
|
||||
};
|
||||
|
||||
@@ -64,8 +64,5 @@ exports.parse = function() {
|
||||
$tw.utils.addAttributeToParseTreeNode(tree[t],"style",styles.join(""));
|
||||
}
|
||||
}
|
||||
return [{
|
||||
type: "void",
|
||||
children: tree
|
||||
}]
|
||||
return tree;
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ exports.types = {inline: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match /@@(styles)?\s*(\.class\s+)?/
|
||||
// Regexp to match
|
||||
this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?(\.(?:[^\r\n\s]+)\s+)?/mg;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -60,37 +60,22 @@ exports.parse = function() {
|
||||
var parser = this.parser.wiki.parseText(parseType,text,{defaultType: "text/plain"});
|
||||
// If there's no render type, just return the parse tree
|
||||
if(!renderType) {
|
||||
return [{
|
||||
type: "void",
|
||||
children: $tw.utils.isArray(parser.tree) ? parser.tree : [parser.tree],
|
||||
parseType: parseType,
|
||||
renderType: renderType,
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}];
|
||||
return parser.tree;
|
||||
} else {
|
||||
// Otherwise, render to the rendertype and return in a <PRE> tag
|
||||
var widgetNode = this.parser.wiki.makeWidget(parser),
|
||||
container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
|
||||
// Use void node to carry important info for typedblock
|
||||
text = renderType === "text/html" ? container.innerHTML : container.textContent;
|
||||
return [{
|
||||
type: "void",
|
||||
type: "element",
|
||||
tag: "pre",
|
||||
children: [{
|
||||
type: "element",
|
||||
tag: "pre",
|
||||
children: [{
|
||||
type: "text",
|
||||
text: renderResult,
|
||||
}]
|
||||
}],
|
||||
parseType: parseType,
|
||||
renderType: renderType,
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
type: "text",
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -215,8 +215,8 @@ WikiParser.prototype.parsePragmas = function() {
|
||||
var subTree = nextMatch.rule.parse();
|
||||
if(subTree.length > 0) {
|
||||
// Set the start and end positions of the pragma rule if
|
||||
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment
|
||||
currentTreeBranch.push.apply(currentTreeBranch,subTree);
|
||||
@@ -245,9 +245,9 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
|
||||
var start = this.pos;
|
||||
var subTree = nextMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last blocks if they're not already set
|
||||
if(subTree.length > 0) {
|
||||
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
if (subTree.length > 0) {
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
return subTree;
|
||||
@@ -256,7 +256,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
|
||||
var start = this.pos;
|
||||
var children = this.parseInlineRun(terminatorRegExp);
|
||||
var end = this.pos;
|
||||
return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseblock" }];
|
||||
return [{type: "element", tag: "p", children: children, start: start, end: end }];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -350,10 +350,10 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
|
||||
var start = this.pos;
|
||||
var subTree = nextMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if(subTree.length > 0) {
|
||||
if (subTree.length > 0) {
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
tree.push.apply(tree,subTree);
|
||||
@@ -410,9 +410,9 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx
|
||||
var start = this.pos;
|
||||
var subTree = inlineRuleMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if(subTree.length > 0) {
|
||||
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
if (subTree.length > 0) {
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; });
|
||||
tree.push.apply(tree,subTree);
|
||||
|
||||
@@ -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" ]);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user