1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-02-20 08:59:50 +00:00

Compare commits

...

60 Commits

Author SHA1 Message Date
saqimtiaz
29b09ab172 lint: updated eslint config with selected rules from #9669 2026-02-20 08:52:52 +01:00
saqimtiaz
8772a9c500 lint: missed files 2026-02-19 19:16:23 +01:00
saqimtiaz
76be64d2ba lint: added more fixes for unused vars 2026-02-19 19:12:54 +01:00
saqimtiaz
3cf26842ae lint: first back of manual lint fixes for unused vars 2026-02-19 18:03:30 +01:00
saqimtiaz
5deb88ad54 lint: allow hashbang comment for tiddlywiki.js 2026-02-19 17:33:35 +01:00
saqimtiaz
450a99b289 fix: apply automatic eslint fixes 2026-02-19 17:24:57 +01:00
Saq Imtiaz
08f2b8bdf4 Fixes variable enumeration in widgets (#9648)
* fix: variable enumeration in widgets

* fix: fakeWidget should have a variables property

* fix: don't use spread properties

* fix: resolve more embarassing bugs

* chore: tests and whitespace

* fix: simplify opts check
2026-02-19 11:14:19 +00:00
Jeremy Ruston
c305eb01eb Fix passing a filtered attribute as a MVV (#9663) 2026-02-19 12:11:39 +01:00
Jeremy Ruston
71462143bf Fix BackgroundActions example 2026-02-16 18:16:45 +00:00
Théophile Desmedt
909149a347 [fix] Remove overflow:hidden on the tiddler info pannel, allowing popups to escape the info pannel (#9660)
* [fix] Remove overflow:hidden on the tiddler info pannel, allowing popups to escape the pannel

* add change note
2026-02-15 18:57:48 +00:00
Mario Pietsch
a2543cfd4a 5.4.0 Update German translations (#9655)
* Update German translations

* Add change note

* Update languages/de-DE/Draft.multids

Co-authored-by: XLBilly <LeiYiXia29@outlook.com>

---------

Co-authored-by: XLBilly <LeiYiXia29@outlook.com>
2026-02-14 21:26:02 +01:00
Jeremy Ruston
b713d13c5a Accidentally committed with #9657 2026-02-13 17:39:12 +00:00
Jeremy Ruston
bb05bd8817 Improve Release Note Presentation (#9657)
* First pass

* UI Tweaks

* Add some colour (possibly too much)

* Corrections

* More tweaks

* Various change note fixes
2026-02-11 18:12:52 +00:00
Mario Pietsch
42a908e1c9 set arrow function parens to always (#9590) 2026-02-10 12:35:10 +01:00
Cameron Fischer
70689a6de4 keyboard-driven-input couldn't use slots well (#9649)
Now it can, at least now without strange and arbitary tweaks to the $depth attribute.
2026-02-10 12:30:08 +01:00
Jeremy Ruston
64ee20edd2 Further MVV fixes (#9645)
* Add ((var)) syntax for passing multi-valued variables through transclude pipeline

Introduce ((var)) attribute syntax to explicitly pass
MVVs to procedures and functions via $transclude, solving the limitation
where <<var>> always resolves to the first value only for backwards
compatibility. Also adds ((var||sep)) and (((filter||sep))) inline display
syntax for debugging MVV values, and multivalued defaults for parameter attributes

* Create pr-draft.md

* Revert "Create pr-draft.md"

This reverts commit dd116af41b.

* Update change note

* Fix linting errors
2026-02-10 12:16:20 +01:00
Théophile Desmedt
0177f09823 Implement translations and indentation fixes for Advanced Info tab (#9643)
* Implement translations and indentation fixes for Advanced Info tab

* update change note

* Update CascadeInfo hint for current tiddler context

Clarified hint for cascade info in TiddlerInfo.

* docs: update github-links in release note #9634
2026-02-08 11:50:12 +01:00
Jeremy Ruston
643cabf9c8 Additional docs for #9641 2026-02-06 16:33:29 +00:00
Jeremy Ruston
5cf3fcd843 Background actions and media query tracking (#9641)
* Initial commit cherry picked from #8702

* Initial docs from #8702

...which need to also be turned into a changenote

* Add changenote
2026-02-06 16:30:46 +00:00
Jeremy Ruston
67f13c585d Fix #9055 docs issue identified in https://github.com/TiddlyWiki/TiddlyWiki5/pull/9055#pullrequestreview-3732792103 2026-02-06 16:24:14 +00:00
Mario Pietsch
1bbb7fd53b Add start- and endactions to link-widget, list-links-draggable and list-tagged-draggable macros (#9621)
* Add start- endactions to link-widget + documentation

* Add start- endactions to list-links-draggable and list-tagged-draggable macros

* Add changenote

* Update docs with actionTiddler info
2026-02-06 14:23:42 +01:00
Saq Imtiaz
599933c34d Remove 'tiddlywiki/dom-to-image' dependency
Removed 'tiddlywiki/dom-to-image' from the tiddlywiki.info
2026-02-06 12:01:22 +01:00
Simon Huber
b1ccb82e0a Update body-toolbar-button - use value={{{ [subfilter{!!button-classes}] :and[join[ ]] }}} (#9585)
* Update body-toolbar-button - use `filter={{!!button-classes}}`

* Update body-toolbar-button.tid

* Create #9566 - button-classes.tid

* Update and rename #9566 - button-classes.tid to #9585 - button-classes.tid

* :and[join[ ]]

* Update how-to guide to mention button-classes
2026-02-06 11:50:43 +01:00
Mohammad Rahmani
ea648c7d15 Update StoryList.tid to Work in Different Layouts (#9094)
* Update StoryList.tid to Work in Different Layouts

See https://talk.tiddlywiki.org/t/stay-organized-by-using-multiple-desktops-in-tiddlywiki/12752/7

All PageTemplate elements are enclosed within that `$navigator` widget, so it should be possible to use those two variables in filters instead of hard-coding the values.

* Apply suggestion from @saqimtiaz

---------

Co-authored-by: Saq Imtiaz <saq.imtiaz@gmail.com>
2026-02-06 11:46:18 +01:00
Jeremy Ruston
a3a4e91751 New dom-to-image plugin for saving DOM nodes as an image (#8810)
* Add tm-save-dom-to-image message

* Temporarily include the geospatial plugin in the Netlify previews

* Scale should default to 1x

* Fix saving SVG images

* Add example of saving in SVG format

* Add library version number

* Document peculiarities of JPEG quality parameter

* Allow format="jpg" as well as the more technically correct "jpeg"

* Document what happens if the selector returns multiple DOM nodes

* Refactor image-to-dom to be a separate plugin

* Add support for oncompletion handler

* Remove ELS marker

Thanks @ericshulman
2026-02-06 10:42:40 +00:00
Mario Pietsch
c96d398712 remove empty.hta from tiddlywiki.info build targets (#9633) 2026-02-06 10:11:23 +00:00
Saq Imtiaz
821dcaf002 Ensures that getting variable info for a function doesnt pollute parent widget (#9639)
* fix: ensure getting variable info for a function doesnt pollute parent widget

* fix: makeFakeWidget should not pollute upstream
2026-02-06 11:10:47 +01:00
Jeremy Ruston
9247a87e11 Missing release note for #8810 2026-02-06 09:09:42 +00:00
Saq Imtiaz
bda54b0ad5 Adds pointer capture and disabling support to eventcatcher widget (#9609)
* feat: eventcatcher with pointer capture support

* fix: various cleanups and improvements

* chore: lint

* chore: lint

* docs: updated eventcatcher docs

* docs: added changenote

* feat: provide access to event properties via JSON blob

* fix: added updated utils file

* fix: guard against missing nodes and not element nodes
2026-02-06 09:16:34 +01:00
Théophile Desmedt
cd8b1faa74 UI: Show cascade filter details in Advanced info tab (#9634)
* UI: Show details on cascade filters in the "Advanced info" tab

* Update CascadeInfo.tid with new formatting

* Remove codeblock for conciseness

* Add change note for #9634

* Refactor CascadeInfo.tid for active filters

Improve filter logic and names of variable

* Change heading names

Updated the CascadeInfo.tid to change 'Active Filter Condition' to 'Active Cascade Filter' and adjusted the corresponding variables.
2026-02-05 19:47:15 +00:00
Saq Imtiaz
0673426f5a fix: remove fn wrappers and unneeded comments (#9637) 2026-02-05 17:06:32 +01:00
Saq Imtiaz
d376ada241 Adds a widget destroy method (#9097)
* feat: widget destroy method

* fix: revert to original implementation

* Invoke onDestroy method during widget destruction

Add custom cleanup method call in destroy process

* Update documentation for destroy method options

* Fix formatting in widget.js comments

* Refactor destroyChildren method for formatting

* Fix indentation in findNextSiblingDomNode method

* docs: added changenote

* chore: lint

* fix: remove deprecated utils method
2026-02-05 17:03:40 +01:00
Mario Pietsch
33b2f514fb Allow title, tags, text as focus for editing existing tiddlers (#9214)
* Allow title, tags, text as focus for editing existing tiddlers

* Add release note

* Update description field

* refresh select widget, it .default parameter is changed

* remove default variable, because it is not needed anymore. select widget refresh handling deals with it

* Undo select widget changes
2026-02-04 13:41:40 +01:00
Saq Imtiaz
46fe3ca988 Revert "Fix RSOE from filter operator errors (#9496)" (#9630)
This reverts commit 86c4770a28.
2026-02-04 12:53:14 +01:00
XLBilly
bf7c0b575c Fix side effects of PR 9316 (#9568)
* Fix color transition not working

* Fix plugin install button

* Fix remove tag button

* Update change note
2026-02-04 12:43:40 +01:00
XLBilly
b236373064 Intergrate tiddlywiki palette colors and settings to custom CSS properties (#9333)
* Expose tiddlywiki palette colors and settings to custom CSS properties

* Rename & use --tc prefix

* Add colors and CSS  settings

* Make CSS settings properties' name readable

* Add all CSS settings

* Add all palette colors

* Remove macrocallblock rule

* Indent with tabs

* Use --tc-color prefix

* Update docs

* Use --tpc prefix

* Add change note

* Simplify palette color rules with list widget

* Update docs

* Hardcode custom properties

* Update docs

* Remove cascades

* Update docs

* Add more docs

* Update docs

* Update docs

* Add --tp-animation-duration

* Update change note
The previous example actually doesn't work at all

* Update docs about limits of CSS variables
2026-02-04 11:37:04 +00:00
Mario Pietsch
d15398fc09 Simple TOC level parameter (#9612)
* Add toc level parameter

* Update TOC documentation

* Add toc level release note

* Update releasenote number and GH links

* Update releasenote number and GH links
2026-02-04 11:26:31 +00:00
Jeremy Ruston
6bc77cf3e2 Dynamic parameters for macro/procedure/function calls (#9055)
* Initial commit

The idea is to extend the macro call syntax to accept dynamic parameter values (ie thing:{{more}} etc). Eventually, this will work in all the contexts in which the double angle bracket syntax is valid.

This initial commit gets the tests passing, but doesn't yet activate the new functionality.

* Test for standalone macro calls with dynamic parameters

* Parse attribute macros with the new parser

This fixes the tests

* Test for attribute macros

* Add some examples

* Tweak examples

* Fix test

* Temporarily disable a broken serializer test

* Fix/dynamic macro calls test (#9459)

* Revert "Temporarily disable a broken serializer test"

This reverts commit b3144300ee.

* restore synamic parameter parse result

* lint

* lint

* remove duplicate

* Update core/modules/parsers/parseutils.js

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update editions/test/tiddlers/tests/data/serialize/DynamicWidgetAttribute.tid

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update editions/test/tiddlers/tests/data/serialize/DynamicWidgetAttribute.tid

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: mixed qouted and unquoted

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix unneeded diff

* Minor docs update

* Genuflecting to the linter

* Remove debug logging

* Add change note

* Allow single closing square brackets within double square brackets quoted strings

* Only allow new style parameter values if the separator is an equals sign

* On reflection, new style values should not be allowed for anonymous parameters

Backwards compatibility

* Docs updates

* Docs updates

---------

Co-authored-by: lin onetwo <linonetwo012@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 11:24:06 +00:00
XLBilly
dc764b3a4a Replace fill rules in tw5.com edition (#9624) 2026-02-04 11:22:32 +00:00
XLBilly
9c09841eda Make draft title translatable (#8891)
* Make draft title translatable

* Update change note

* Improve number handling
Now generates "Draft of '...' 2" instead of "Draft 2 of '...'"

* Improve whitespace handling
We no longer needs to add whitespace in languages. We now handle it in javascript.

* Update language naming

* Update zh-Hans translation

* Update change note

* Refactor logic to make it less complex
Since we don't need to care about draft numbers, we can have two different templates for draft title with and without attribution. No need to trim the string now.
Also, we can reuse the getSubstitutedText method

* Update translators edition

* fixup! Update translators edition

* Switch to transclude and variable mechanism

* Adapt translators to the new mechanism

* Update change note

* Further simplify the logic
$tw.language.getString can already wikify translatable strings. No need for this.renderText
2026-02-04 11:21:54 +00:00
Cameron Fischer
9d5be2e9f8 Recurse exception handling to better handle '{{}}' in place of recently installed fix (#9548)
* Introduced preliminary idea for infinite recurse exception

* Better handling of infinite recursion

But it could be better still...

* the TransclusionError is a proper error

Moved the magic number to be on the error's class. Not sure if that's
a great idea.

* Fixed minor minor issue that came up in conflict

The minor fix to the jasmine regexp that escaped a '+' somehow
broke some random test.

* Removing patch fix for recursion errors

* Fixed issue where buttton and other widgets don't clean up

* Added release notes for #9548

* Update test-widget.js

If I don't fix those indentations, the entire TW codebase will explode or soemthing.

* Update test-widget.js

These lint problems are wasting my time.

* Fixed all core widgets to not leak when renderChildren fails

* Updated release notes to reflect what I'm actually fixing

* Update test-widget.js

Added warning not to use for-of loop for defining tests. The iterating variable needs to have its own method scope, or it risks being the same value for all tests.
2026-02-04 11:21:16 +00:00
lin onetwo
486d3bd326 Fix sitemap plugin can't provide xml content type in GET route (#9203)
* Update get-tiddler-html.js

* Create #9203.tid
2026-02-04 11:19:56 +00:00
XLBilly
196683915c Replace window.eval with Function (#9611)
* Replace window.eval with Function

* Add back comment
2026-02-04 11:17:10 +00:00
yaisog
42a3928960 Refactor code for EditTemplate fields (#9582)
* Refactored fields.tid

* Add changenote

* Optimize indentation and remove unneeded variable

* Consolidate some variables, procedures and functions

* Streamlined conditional and reveal structures

* Eliminate the fieldmangler widget

* Add tc-edit-field-exists to new field name input if applicable

* Call save-tiddler-actions on Ctrl-Enter in name input field
2026-02-04 11:13:53 +00:00
Saq Imtiaz
2e76cc08a1 Extends image widget with support for data-attributes and on load actions (#9050)
* feat: support for data-attributes and on load actions

* feat: support for data-attributes and on load actions

* fix: typo

* fix: simplify variable assignment

* docs: added changenote
2026-02-04 11:12:58 +00:00
Saq Imtiaz
891e4fcb2b Fixes a regression in correctly evaluating default param values for functions (#9614)
* Fix: bug in multivalue default params

* Enhance release notes for version 5.4.0

Updated GitHub links and contributors for release notes.

* Add FunctionDefaultValues test for default parameters

* Update function default values in FunctionDefaultValues.tid

* Update #8972.tid

* fix: correctly resolve default values for functions

* Update #8972.tid
2026-02-04 11:12:42 +00:00
Saq Imtiaz
f6fd5ff261 Fixes bug in correctly resolving functions in text substitutions (#9598)
* fix: correctly resolve functions in text substitutions

* docs: added changenote

* fix: remove commented code
2026-02-04 11:12:16 +00:00
XLBilly
526aaa3db8 Bump katex to newest version (#9626)
* Bump katex to newest version

* Update fonts
Also migrate to woff2

* Update readme

* Update change note
2026-02-04 10:11:09 +01:00
XLBilly
455f1be3fb Fix missing semicolon in Snow White (#9625)
* Fix missing comma in Snow White

* Update change note
2026-02-04 10:09:39 +01:00
Mohammad Rahmani
bffa0bb95a Update Documentation for list-tagged-draggable and list-links-draggable. (#9553)
* Update documents for list-links-draggable Macro.tid

add : `<<.from-version 5.4.0>> `

* Update documentation for list-tagged-draggable Macro.tid

Added `<<.from-version 5.4.0>> `

* Update list-links-draggable Macro.tid

Correct extra space and remove colon

* Remove duplicate title view field in list.tid

Removed redundant view field for title in list.tid.
This PR should fix issue reported here: https://github.com/TiddlyWiki/TiddlyWiki5/issues/9555
2026-02-04 10:09:02 +01:00
Jeremy Ruston
a1ef2ef6d4 Merge branch 'tiddlywiki-com' 2026-01-29 14:27:59 +00:00
Saq Imtiaz
75edd9b488 Reverts change to getLocationHash utils method (#9622)
* fix: reverted change to getLocationHash utils method

* docs: update changenote
2026-01-26 16:03:50 +01:00
Mario Pietsch
cde9c931c8 Select widget handle default parameter refresh (#9617)
* select widget handle default parameter refresh

* Add change note
2026-01-25 19:58:52 +01:00
Saq Imtiaz
d07fe25cdb feat: extend fakedom implementation (#9616)
* feat: extend fakedom implementation

* docs: updated changenote
2026-01-25 19:05:46 +01:00
KiXaM_刻む
a40ce29451 Add an option to enable CORS (#9277)
* Add an option to disable CORS

* change 'disable' with 'enable' CORS, because that is what this option actually does

* add a change note

* typo
2026-01-25 17:04:16 +01:00
buggyj
75647eb623 Fixes #8092 SelectWidget does not work with multiple options organise… (#8093)
* Fixes #8092 SelectWidget does not work with multiple options organised into group

* Consolidate variables

* Apply suggestion from @saqimtiaz

* Update core/modules/widgets/select.js

Co-authored-by: Mario Pietsch <pmariojo@gmail.com>

* added release note

* chore: lint fixes

---------

Co-authored-by: Saq Imtiaz <saq.imtiaz@gmail.com>
Co-authored-by: Mario Pietsch <pmariojo@gmail.com>
2026-01-25 17:02:18 +01:00
Mario Pietsch
70b4557738 [DOCS] Add link to "TiddlyWiki Archive" tiddler to the TiddlyWiki Releases info (#9613) 2026-01-25 16:59:54 +01:00
Mario Pietsch
efe58e41bc [DOCS] Fix some typos in "days Operator (Examples)" (#9479)
* [DOCS] Fix some typos in "days Operator (Examples)"

* Remove created and modified fields from days.tid

Remove created and modified fields from days.tid
2026-01-21 09:09:14 +01:00
Mario Pietsch
79e3d14698 [DOCS] Make TaskManagementExamples more "hackable" (#9482)
* [DOCS] Make TaskManagementExamples more "hackable"

* Update modified date in TaskManagementExample.tid

* Fix modified date in TaskManagementExampleDraggable
2026-01-20 13:23:17 +01:00
superuser-does
763d717a13 Improvements to DateFormat tiddler (#9583) 2026-01-20 13:18:24 +01:00
529 changed files with 8139 additions and 4849 deletions

View File

@@ -120,7 +120,6 @@ node $TW5_BUILD_TIDDLYWIKI \
|| exit 1
# /empty.html Empty
# /empty.hta For Internet Explorer
# /empty-external-core.html External core empty
# /tiddlywikicore-<version>.js Core plugin javascript
node $TW5_BUILD_TIDDLYWIKI \

View File

@@ -15,40 +15,40 @@ var fs = require("fs"),
{ optimize } = require("svgo"),
config = {
plugins: [
'cleanupAttrs',
'removeDoctype',
'removeXMLProcInst',
'removeComments',
'removeMetadata',
'removeTitle',
'removeDesc',
'removeUselessDefs',
'removeEditorsNSData',
'removeEmptyAttrs',
'removeHiddenElems',
'removeEmptyText',
'removeEmptyContainers',
"cleanupAttrs",
"removeDoctype",
"removeXMLProcInst",
"removeComments",
"removeMetadata",
"removeTitle",
"removeDesc",
"removeUselessDefs",
"removeEditorsNSData",
"removeEmptyAttrs",
"removeHiddenElems",
"removeEmptyText",
"removeEmptyContainers",
// 'removeViewBox',
'cleanupEnableBackground',
'convertStyleToAttrs',
'convertColors',
'convertPathData',
'convertTransform',
'removeUnknownsAndDefaults',
'removeNonInheritableGroupAttrs',
'removeUselessStrokeAndFill',
'removeUnusedNS',
'cleanupIDs',
'cleanupNumericValues',
'moveElemsAttrsToGroup',
'moveGroupAttrsToElems',
'collapseGroups',
"cleanupEnableBackground",
"convertStyleToAttrs",
"convertColors",
"convertPathData",
"convertTransform",
"removeUnknownsAndDefaults",
"removeNonInheritableGroupAttrs",
"removeUselessStrokeAndFill",
"removeUnusedNS",
"cleanupIDs",
"cleanupNumericValues",
"moveElemsAttrsToGroup",
"moveGroupAttrsToElems",
"collapseGroups",
// 'removeRasterImages',
'mergePaths',
'convertShapeToPath',
'sortAttrs',
"mergePaths",
"convertShapeToPath",
"sortAttrs",
//'removeDimensions',
{name: 'removeAttrs', params: { attrs: '(stroke|fill)' } }
{name: "removeAttrs", params: { attrs: "(stroke|fill)" } }
]
};
@@ -72,7 +72,7 @@ files.forEach(function(filename) {
var newSVG = header.join("\n") + "\n\n" + result.data.replace("&lt;&lt;now &quot;DD&quot;&gt;&gt;","<<now \"DD\">>");
fs.writeFileSync(filepath,newSVG);
} else {
console.log("Error " + err + " with " + filename)
console.log("Error " + err + " with " + filename);
process.exit();
};
}

View File

@@ -12,8 +12,6 @@ On the server this file is executed directly to boot TiddlyWiki. In the browser,
var _boot = (function($tw) {
/*jslint node: true, browser: true */
/*global modules: false, $tw: false */
"use strict";
// Include bootprefix if we're not given module data
@@ -37,7 +35,7 @@ if($tw.node) {
$tw.boot.log = function(str) {
$tw.boot.logMessages = $tw.boot.logMessages || [];
$tw.boot.logMessages.push(str);
}
};
/*
Check if an object has a property
@@ -47,7 +45,7 @@ $tw.utils.hop = function(object,property) {
};
/** @deprecated Use Array.isArray instead */
$tw.utils.isArray = value => Array.isArray(value);
$tw.utils.isArray = (value) => Array.isArray(value);
/*
Check if an array is equal by value and by reference.
@@ -127,7 +125,7 @@ $tw.utils.pushTop = function(array,value) {
};
/** @deprecated Use instanceof Date instead */
$tw.utils.isDate = value => value instanceof Date;
$tw.utils.isDate = (value) => value instanceof Date;
/** @deprecated Use array iterative methods instead */
$tw.utils.each = function(object,callback) {
@@ -138,7 +136,7 @@ $tw.utils.each = function(object,callback) {
return next !== false;
});
} else {
Object.entries(object).every(entry => {
Object.entries(object).every((entry) => {
const next = callback(entry[1], entry[0], object);
return next !== false;
});
@@ -316,8 +314,25 @@ $tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};
/** @deprecated Use window.location.hash instead. */
$tw.utils.getLocationHash = () => window.location.hash;
/*
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
*/
$tw.utils.getLocationHash = function() {
const href = window.location.href,
idx = href.indexOf("#");
if(idx === -1) {
return "#";
}
const afterHash = href.substring(idx + 1);
if(afterHash.startsWith("#") || afterHash.startsWith("%23")) {
// Special case: ignore location hash if it itself starts with a #
return "#";
}
return href.substring(idx);
};
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
$tw.utils.pad = function(value,length = 2) {
@@ -548,7 +563,7 @@ using a lowercase extension only.
*/
$tw.utils.getFileExtensionInfo = function(ext) {
return ext ? $tw.config.fileExtensionInfo[ext.toLowerCase()] : null;
}
};
/*
Given an extension, get the correct encoding for that file.
@@ -571,7 +586,7 @@ var globalCheck =[
" delete Object.prototype.__temp__;",
" }",
" delete Object.prototype.__temp__;",
].join('\n');
].join("\n");
/*
Run code globally with specified context variables in scope
@@ -596,10 +611,10 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
// Compile the code into a function
var fn;
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename); // eslint-disable-line no-eval -- See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
fn = Function("return " + code + "\n\n//# sourceURL=" + filename)(); // See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
} else {
if(sandbox){
fn = vm.runInContext(code,sandbox,filename)
fn = vm.runInContext(code,sandbox,filename);
} else {
fn = vm.runInThisContext(code,filename);
}
@@ -710,7 +725,7 @@ $tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
var self = this;
form.addEventListener("submit",function(event) {
// Collect the form data
var data = {},t;
var data = {};
$tw.utils.each(form.elements,function(element) {
if(element.name && element.value) {
data[element.name] = element.value;
@@ -756,7 +771,7 @@ $tw.utils.PasswordPrompt.prototype.removePrompt = function(promptInfo) {
promptInfo.form.parentNode.removeChild(promptInfo.form);
this.setWrapperDisplay();
}
}
};
/*
Crypto helper object for encrypted content. It maintains the password text in a closure, and provides methods to change
@@ -795,7 +810,7 @@ $tw.utils.Crypto = function() {
};
this.hasPassword = 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"});
@@ -813,7 +828,7 @@ Execute the module named 'moduleName'. The name can optionally be relative to th
$tw.modules.execute = function(moduleName,moduleRoot) {
var name = moduleName;
if(moduleName.charAt(0) === ".") {
name = $tw.utils.resolvePath(moduleName,moduleRoot)
name = $tw.utils.resolvePath(moduleName,moduleRoot);
}
if(!$tw.modules.titles[name]) {
if($tw.modules.titles[name + ".js"]) {
@@ -874,7 +889,6 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
if(!moduleInfo) {
// We could not find the module on this path
// Try to defer to browserify etc, or node
var deferredModule;
if($tw.browser) {
if(window.require) {
try {
@@ -1129,8 +1143,7 @@ enableIndexers - Array of indexer names to enable, or null to use all available
*/
$tw.Wiki = function(options) {
options = options || {};
var self = this,
tiddlers = Object.create(null), // Hashmap of tiddlers
var tiddlers = Object.create(null), // Hashmap of tiddlers
tiddlerTitles = null, // Array of tiddler titles
getTiddlerTitles = function() {
if(!tiddlerTitles) {
@@ -1184,7 +1197,7 @@ $tw.Wiki = function(options) {
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
};
// Save the new tiddler
tiddlers[title] = tiddler;
// Check we've got the title
@@ -1194,7 +1207,7 @@ $tw.Wiki = function(options) {
tiddler: tiddler,
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
};
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
@@ -1219,7 +1232,7 @@ $tw.Wiki = function(options) {
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
};
// Delete the tiddler
delete tiddlers[title];
// Delete it from the list of titles
@@ -1234,7 +1247,7 @@ $tw.Wiki = function(options) {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
};
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
@@ -1422,8 +1435,7 @@ $tw.Wiki = function(options) {
// Unregister the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting unregistering to an array of tiddler titles. Returns an array of the titles affected
this.unregisterPluginTiddlers = function(pluginType,titles) {
var self = this,
unregisteredTitles = [];
var unregisteredTitles = [];
// Remove any previous registered plugins of this type
for(var t=pluginTiddlers.length-1; t>=0; t--) {
var tiddler = pluginTiddlers[t];
@@ -1437,16 +1449,15 @@ $tw.Wiki = function(options) {
// Unpack the currently registered plugins, creating shadow tiddlers for their constituent tiddlers
this.unpackPluginTiddlers = function() {
var self = this;
// Sort the plugin titles by the `plugin-priority` field, if this field is missing, default to 1
pluginTiddlers.sort(function(a, b) {
var priorityA = "plugin-priority" in a.fields ? a.fields["plugin-priority"] : 1;
var priorityB = "plugin-priority" in b.fields ? b.fields["plugin-priority"] : 1;
if (priorityA !== priorityB) {
if(priorityA !== priorityB) {
return priorityA - priorityB;
} else if (a.fields.title < b.fields.title) {
} else if(a.fields.title < b.fields.title) {
return -1;
} else if (a.fields.title === b.fields.title) {
} else if(a.fields.title === b.fields.title) {
return 0;
} else {
return +1;
@@ -1553,7 +1564,7 @@ $tw.Wiki.prototype.processSafeMode = function() {
// Assemble a report tiddler
var titleReportTiddler = "TiddlyWiki Safe Mode",
report = [];
report.push("TiddlyWiki has been started in [[safe mode|https://tiddlywiki.com/static/SafeMode.html]]. All plugins are temporarily disabled. Most customisations have been disabled by renaming the following tiddlers:")
report.push("TiddlyWiki has been started in [[safe mode|https://tiddlywiki.com/static/SafeMode.html]]. All plugins are temporarily disabled. Most customisations have been disabled by renaming the following tiddlers:");
// Delete the overrides
overrides.forEach(function(title) {
var tiddler = self.getTiddler(title),
@@ -1562,7 +1573,7 @@ $tw.Wiki.prototype.processSafeMode = function() {
self.addTiddler(new $tw.Tiddler(tiddler, {title: newTitle}));
report.push("* [[" + title + "|" + newTitle + "]]");
});
report.push()
report.push();
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
// Set $:/DefaultTiddlers to point to our report
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
@@ -1996,7 +2007,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
value = $tw.utils.stringifyList(path.relative(rootPath, filename).split(path.sep).slice(0, -1));
break;
case "filepath":
value = path.relative(rootPath, filename).split(path.sep).join('/');
value = path.relative(rootPath, filename).split(path.sep).join("/");
break;
case "filename":
value = path.basename(filename);
@@ -2049,7 +2060,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
}
});
return arrayOfFiles;
}
};
// Process the listed tiddlers
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
if(tidInfo.prefix && tidInfo.suffix) {
@@ -2158,7 +2169,7 @@ Returns the path of the plugin folder
$tw.findLibraryItem = function(name,paths) {
var pathIndex = 0;
do {
var pluginPath = path.resolve(paths[pathIndex],"./" + name)
var pluginPath = path.resolve(paths[pathIndex],"./" + name);
if(fs.existsSync(pluginPath) && fs.statSync(pluginPath).isDirectory()) {
return pluginPath;
}
@@ -2517,7 +2528,7 @@ $tw.boot.initStartup = function(options) {
}
});
return result;
}
};
}
};
$tw.boot.loadStartup = function(options){
@@ -2534,7 +2545,7 @@ $tw.boot.loadStartup = function(options){
}
// Give hooks a chance to modify the store
$tw.hooks.invokeHook("th-boot-tiddlers-loaded");
}
};
$tw.boot.execStartup = function(options){
// Unpack plugin tiddlers
$tw.wiki.readPluginInfo();
@@ -2564,7 +2575,7 @@ $tw.boot.execStartup = function(options){
$tw.boot.disabledStartupModules = $tw.boot.disabledStartupModules || [];
// Repeatedly execute the next eligible task
$tw.boot.executeNextStartupTask(options.callback);
}
};
/*
Startup TiddlyWiki
*/
@@ -2583,7 +2594,7 @@ $tw.addUnloadTask = function(task) {
if($tw.unloadTasks.indexOf(task) === -1) {
$tw.unloadTasks.push(task);
}
}
};
/*
Execute the remaining eligible startup tasks
@@ -2630,7 +2641,7 @@ $tw.boot.executeNextStartupTask = function(callback) {
}
taskIndex++;
}
if(typeof callback === 'function') {
if(typeof callback === "function") {
callback();
}
return false;

View File

@@ -103,7 +103,7 @@ Commander.prototype.executeNextCommand = function() {
c = new command.Command(params,this);
err = c.execute();
if(err && typeof err.then === "function") {
err.then(e => { e ? this.callback(e) : this.executeNextCommand(); });
err.then((e) => { e ? this.callback(e) : this.executeNextCommand(); });
} else if(err) {
this.callback(err);
} else {
@@ -120,7 +120,7 @@ Commander.prototype.executeNextCommand = function() {
});
err = c.execute();
if(err && typeof err.then === "function") {
err.then(e => { if(e) this.callback(e); });
err.then((e) => { if(e) this.callback(e); });
} else if(err) {
this.callback(err);
}

View File

@@ -25,7 +25,7 @@ Command.prototype.execute = function() {
if(!filter) {
return "No filter specified";
}
var commands = this.commander.wiki.filterTiddlers(filter)
var commands = this.commander.wiki.filterTiddlers(filter);
if(commands.length === 0) {
return "No tiddlers found for filter '" + filter + "'";
}

View File

@@ -24,8 +24,7 @@ Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filter";
}
var self = this,
wiki = this.commander.wiki,
var wiki = this.commander.wiki,
filter = this.params[0],
tiddlers = wiki.filterTiddlers(filter);
$tw.utils.each(tiddlers,function(title) {

View File

@@ -66,7 +66,7 @@ Command.prototype.fetchFiles = function(options) {
// Get the list of URLs
var urls;
if(options.url) {
urls = [options.url]
urls = [options.url];
} else if(options.urlFilter) {
urls = this.commander.wiki.filterTiddlers(options.urlFilter);
} else {
@@ -96,30 +96,30 @@ Command.prototype.fetchFile = function(url,options,callback,redirectCount) {
var self = this,
lib = url.substr(0,8) === "https://" ? require("https") : require("http");
lib.get(url).on("response",function(response) {
var type = (response.headers["content-type"] || "").split(";")[0],
data = [];
self.commander.write("Reading " + url + ": ");
response.on("data",function(chunk) {
data.push(chunk);
self.commander.write(".");
});
response.on("end",function() {
self.commander.write("\n");
if(response.statusCode === 200) {
self.processBody(Buffer.concat(data),type,options,url);
callback(null);
} else {
if(response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) {
return self.fetchFile(response.headers.location,options,callback,redirectCount + 1);
} else {
return callback("Error " + response.statusCode + " retrieving " + url)
}
}
});
response.on("error",function(e) {
var type = (response.headers["content-type"] || "").split(";")[0],
data = [];
self.commander.write("Reading " + url + ": ");
response.on("data",function(chunk) {
data.push(chunk);
self.commander.write(".");
});
response.on("end",function() {
self.commander.write("\n");
if(response.statusCode === 200) {
self.processBody(Buffer.concat(data),type,options,url);
callback(null);
} else {
if(response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) {
return self.fetchFile(response.headers.location,options,callback,redirectCount + 1);
} else {
return callback("Error " + response.statusCode + " retrieving " + url);
}
}
});
response.on("error",function(e) {
console.log("Error on GET request: " + e);
callback(e);
});
});
});
return null;
};
@@ -153,18 +153,18 @@ Command.prototype.processBody = function(body,type,options,url) {
if(options.transformFilter) {
var transformedTitle = (incomingWiki.filterTiddlers(options.transformFilter,null,self.commander.wiki.makeTiddlerIterator([title])) || [""])[0];
if(transformedTitle) {
self.commander.log("Importing " + title + " as " + transformedTitle)
self.commander.log("Importing " + title + " as " + transformedTitle);
newTiddler = new $tw.Tiddler(tiddler,{title: transformedTitle});
}
} else {
self.commander.log("Importing " + title)
self.commander.log("Importing " + title);
newTiddler = tiddler;
}
self.commander.wiki.importTiddler(newTiddler);
count++;
}
});
self.commander.log("Imported " + count + " tiddlers")
self.commander.log("Imported " + count + " tiddlers");
};
exports.Command = Command;

View File

@@ -22,8 +22,7 @@ var Command = function(params,commander,callback) {
Command.prototype.execute = function() {
var self = this,
fs = require("fs"),
path = require("path");
fs = require("fs");
if(this.params.length < 2) {
return "Missing parameters";
}

View File

@@ -20,8 +20,7 @@ var Command = function(params,commander) {
};
Command.prototype.execute = function() {
var fs = require("fs"),
path = require("path");
var fs = require("fs");
// Check that we don't already have a valid wiki folder
if($tw.boot.wikiTiddlersPath || ($tw.utils.isDirectory($tw.boot.wikiPath) && !$tw.utils.isDirectoryEmpty($tw.boot.wikiPath))) {
return "Wiki folder is not empty";

View File

@@ -19,7 +19,6 @@ exports.info = {
};
var Command = function(params,commander,callback) {
var self = this;
this.params = params;
this.commander = commander;
this.callback = callback;

View File

@@ -21,9 +21,7 @@ var Command = function(params,commander,callback) {
};
Command.prototype.execute = function() {
var self = this,
fs = require("fs"),
path = require("path");
var self = this;
if(this.params.length < 1) {
return "Missing filename";
}

View File

@@ -21,8 +21,7 @@ var Command = function(params,commander,callback) {
};
Command.prototype.execute = function() {
var fs = require("fs"),
path = require("path");
var path = require("path");
if(this.params.length < 1) {
return "Missing output path";
}

View File

@@ -7,59 +7,57 @@ Render individual tiddlers and save the results to the specified files
\*/
"use strict";
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "render",
synchronous: true
};
exports.info = {
name: "render",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing tiddler filter";
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing tiddler filter";
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.utils.each(tiddlers,function(title) {
var filenameResults = wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]));
if(filenameResults.length > 0) {
var filepath = path.resolve(self.commander.outputPath,filenameResults[0]);
if(self.commander.verbose) {
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
}
var parser = wiki.parseTiddler(template || title),
widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title,storyTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent;
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,text,"utf8");
} else {
console.log("Not rendering \"" + title + "\" because the filename filter returned an empty result");
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.utils.each(tiddlers,function(title) {
var filenameResults = wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]));
if(filenameResults.length > 0) {
var filepath = path.resolve(self.commander.outputPath,filenameResults[0]);
if(self.commander.verbose) {
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
}
var parser = wiki.parseTiddler(template || title),
widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title,storyTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent;
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,text,"utf8");
} else {
console.log("Not rendering \"" + title + "\" because the filename filter returned an empty result");
}
});
return null;
};
});
return null;
};
exports.Command = Command;
exports.Command = Command;

View File

@@ -9,8 +9,6 @@ Command to render several tiddlers to a folder of files
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "rendertiddlers",
synchronous: true

View File

@@ -7,57 +7,56 @@ Saves individual tiddlers in their raw text or binary format to the specified fi
\*/
"use strict";
"use strict";
exports.info = {
name: "save",
synchronous: true
};
exports.info = {
name: "save",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filename filter";
}
var self = this,
fs = require("fs"),
path = require("path"),
result = null,
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]]",
tiddlers = wiki.filterTiddlers(tiddlerFilter);
$tw.utils.each(tiddlers,function(title) {
if(!result) {
var tiddler = self.commander.wiki.getTiddler(title);
if(tiddler) {
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: path.resolve(self.commander.outputPath),
pathFilters: [filenameFilter],
wiki: wiki,
fileInfo: {
overwrite: true
}
});
if(self.commander.verbose) {
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filename filter";
}
var self = this,
path = require("path"),
result = null,
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]]",
tiddlers = wiki.filterTiddlers(tiddlerFilter);
$tw.utils.each(tiddlers,function(title) {
if(!result) {
var tiddler = self.commander.wiki.getTiddler(title);
if(tiddler) {
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: path.resolve(self.commander.outputPath),
pathFilters: [filenameFilter],
wiki: wiki,
fileInfo: {
overwrite: true
}
try {
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
} catch (err) {
result = "Error saving tiddler \"" + title + "\", to file: \"" + fileInfo.filepath + "\"";
}
} else {
result = "Tiddler '" + title + "' not found";
});
if(self.commander.verbose) {
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
}
try {
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
} catch (err) {
result = "Error saving tiddler \"" + title + "\", to file: \"" + fileInfo.filepath + "\"";
}
} else {
result = "Tiddler '" + title + "' not found";
}
});
return result;
};
}
});
return result;
};
exports.Command = Command;
exports.Command = Command;

View File

@@ -9,8 +9,6 @@ Command to save several tiddlers to a folder of files
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "savetiddlers",
synchronous: true

View File

@@ -43,7 +43,7 @@ Command.prototype.execute = function() {
namedParames,
tiddlerFilter,
options = {};
if (regFilter.test(this.params[1])) {
if(regFilter.test(this.params[1])) {
namedParames = this.commander.extractNamedParameters(this.params.slice(1));
tiddlerFilter = namedParames.filter || "[all[tiddlers]]";
} else {
@@ -177,13 +177,13 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
$tw.utils.each(pluginTiddlers,function(tiddler,title) {
if(!tiddler.title) {
tiddler.title = title;
}
}
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
});
};
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
var title = tiddler.fields.title, fileInfo, pathFilters, extFilters;
var fileInfo, pathFilters, extFilters;
if(this.wiki.tiddlerExists("$:/config/FileSystemPaths")) {
pathFilters = this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n");
}

View File

@@ -17,7 +17,6 @@ exports.info = {
};
var Command = function(params,commander,callback) {
var self = this;
this.params = params;
this.commander = commander;
this.callback = callback;

View File

@@ -9,8 +9,6 @@ Command to modify selected tiddlers to set a field to the text of a template tid
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "setfield",
synchronous: true
@@ -26,8 +24,7 @@ Command.prototype.execute = function() {
if(this.params.length < 4) {
return "Missing parameters";
}
var self = this,
wiki = this.commander.wiki,
var wiki = this.commander.wiki,
filter = this.params[0],
fieldname = this.params[1] || "text",
templatetitle = this.params[2],

View File

@@ -26,7 +26,7 @@ exports.getSubdirectories = function(dirPath) {
}
});
return subdirs;
}
};
/*
Recursively (and synchronously) copy a directory and all its content
@@ -46,8 +46,7 @@ exports.copyDirectory = function(srcPath,dstPath) {
}
// Function to copy a folder full of files
var copy = function(srcPath,dstPath) {
var srcStats = fs.lstatSync(srcPath),
dstExists = fs.existsSync(dstPath);
var srcStats = fs.lstatSync(srcPath);
if(srcStats.isFile()) {
$tw.utils.copyFile(srcPath,dstPath);
} else if(srcStats.isDirectory()) {
@@ -83,7 +82,7 @@ exports.copyFile = function(srcPath,dstPath) {
dstFile = fs.openSync(dstPath,"w"),
bytesRead = 1,
pos = 0;
while (bytesRead > 0) {
while(bytesRead > 0) {
bytesRead = fs.readSync(srcFile,fileBuffer,0,FILE_BUFFER_LENGTH,pos);
fs.writeSync(dstFile,fileBuffer,0,bytesRead);
pos += bytesRead;
@@ -148,7 +147,7 @@ exports.deleteDirectory = function(dirPath) {
fs.unlinkSync(currPath);
}
}
fs.rmdirSync(dirPath);
fs.rmdirSync(dirPath);
}
return null;
};
@@ -255,7 +254,7 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
// Overriding to the .tid extension needs special handling
fileInfo.type = "application/x-tiddler";
fileInfo.hasMetaFile = false;
} else if (metaExt === ".json") {
} else if(metaExt === ".json") {
// Overriding to the .json extension needs special handling
fileInfo.type = "application/json";
fileInfo.hasMetaFile = false;
@@ -345,18 +344,18 @@ exports.generateTiddlerFilepath = function(title,options) {
// Replace any Windows control codes
filepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
// Replace any leading spaces with the same number of underscores
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_")});
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_");});
//If the path does not start with "." or ".." && a path seperator, then
if(!/^\.{1,2}[/\\]/g.test(filepath)) {
// Don't let the filename start with any dots because such files are invisible on *nix
filepath = filepath.replace(/^\.+/g,function (u) { return u.replace(/\./g, "_")});
filepath = filepath.replace(/^\.+/g,function (u) { return u.replace(/\./g, "_");});
}
// Replace any Unicode control codes
filepath = filepath.replace(/[\x00-\x1f\x80-\x9f]/g,"_");
// Replace any characters that can't be used in cross-platform filenames
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
// Replace any dots or spaces at the end of the extension with the same number of underscores
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_")});
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_");});
// Truncate the extension if it is too long
if(extension.length > 32) {
extension = extension.substr(0,32);
@@ -382,9 +381,9 @@ exports.generateTiddlerFilepath = function(title,options) {
}
// Add a uniquifier if the file already exists (default)
var fullPath = path.resolve(directory, filepath + extension);
if (!overwrite) {
if(!overwrite) {
var oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
count = 0;
count = 0;
do {
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
if(oldPath && oldPath == fullPath) break;
@@ -401,7 +400,7 @@ exports.generateTiddlerFilepath = function(title,options) {
writePath.indexOf(path.resolve(directory)) == 0 ||
writePath.indexOf(path.resolve($tw.boot.wikiPath)) == 0 ||
writePath.indexOf(path.resolve($tw.boot.wikiTiddlersPath,originalpath)) == 0 );
}
}
if(encode) {
writePath = path.resolve(directory,$tw.utils.encodeURIComponentExtended(fullPath));
}
@@ -521,12 +520,12 @@ Cleanup old files on disk, by comparing the options values:
*/
exports.cleanupTiddlerFiles = function(options,callback) {
var adaptorInfo = options.adaptorInfo || {},
bootInfo = options.bootInfo || {},
title = options.title || "undefined";
bootInfo = options.bootInfo || {},
title = options.title || "undefined";
if(adaptorInfo.filepath && bootInfo.filepath && adaptorInfo.filepath !== bootInfo.filepath) {
$tw.utils.deleteTiddlerFile(adaptorInfo,function(err) {
if(err) {
if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") {
if((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") {
// Error deleting the previous file on disk, should fail gracefully
$tw.syncer.displayError("Server desynchronized. Error cleaning up previous file for tiddler: \""+title+"\"",err);
return callback(null,bootInfo);

View File

@@ -10,9 +10,7 @@ Authenticator for WWW basic authentication
"use strict";
if($tw.node) {
var util = require("util"),
fs = require("fs"),
url = require("url"),
var fs = require("fs"),
path = require("path");
}

View File

@@ -19,7 +19,7 @@ exports.info = {
exports.handler = function(request,response,state) {
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
responseHeaders = {
"Content-Type": state.server.get("root-serve-type")
};
"Content-Type": state.server.get("root-serve-type")
};
state.sendResponse(200,responseHeaders,text);
};

View File

@@ -33,8 +33,8 @@ exports.handler = function(request,response,state) {
}
var text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}});
// Naughty not to set a content-type, but it's the easiest way to ensure the browser will see HTML pages as HTML, and accept plain text tiddlers as CSS or JS
state.sendResponse(200,{},text,"utf8");
var headers = {"Content-Type": renderType};
state.sendResponse(200,headers,text,"utf8");
} else {
response.writeHead(404);
response.end();

View File

@@ -18,7 +18,7 @@ exports.info = {
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
fields = $tw.utils.parseJSONSafe(state.data);
fields = $tw.utils.parseJSONSafe(state.data);
// Pull up any subfields in the `fields` object
if(fields.fields) {
$tw.utils.each(fields.fields,function(field,name) {

View File

@@ -9,14 +9,15 @@ Serve tiddlers over http
"use strict";
let fs, url, path, querystring, crypto, zlib;
if($tw.node) {
var util = require("util"),
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
}
/*
@@ -41,7 +42,9 @@ function Server(options) {
}
}
// Setup the default required plugins
this.requiredPlugins = this.get("required-plugins").split(',');
this.requiredPlugins = this.get("required-plugins").split(",");
// Initialise CORS
this.corsEnable = this.get("cors-enable") === "yes";
// Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression
@@ -60,9 +63,9 @@ function Server(options) {
this.authorizationPrincipals = {
readers: (this.get("readers") || authorizedUserName).split(",").map($tw.utils.trim),
writers: (this.get("writers") || authorizedUserName).split(",").map($tw.utils.trim)
}
};
if(this.get("admin") || authorizedUserName !== "(anon)") {
this.authorizationPrincipals["admin"] = (this.get("admin") || authorizedUserName).split(',').map($tw.utils.trim)
this.authorizationPrincipals["admin"] = (this.get("admin") || authorizedUserName).split(",").map($tw.utils.trim);
}
// Load and initialise authenticators
$tw.modules.forEachModuleOfType("authenticator", function(title,authenticatorDefinition) {
@@ -89,7 +92,7 @@ function Server(options) {
this.listenOptions = {
key: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsKeyFilepath),"utf8"),
cert: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsCertFilepath),"utf8"),
passphrase: tlsPassphrase || ''
passphrase: tlsPassphrase || ""
};
this.protocol = "https";
}
@@ -114,7 +117,7 @@ encoding: the encoding of the data to send (passed to the end method of the resp
*/
function sendResponse(request,response,statusCode,headers,data,encoding) {
if(this.enableBrowserCache && (statusCode == 200)) {
var hash = crypto.createHash('md5');
var hash = crypto.createHash("md5");
// Put everything into the hash that could change and invalidate the data that
// the browser already stored. The headers the data and the encoding.
hash.update(data);
@@ -209,7 +212,6 @@ Server.prototype.addAuthenticator = function(AuthenticatorClass) {
Server.prototype.findMatchingRoute = function(request,state) {
for(var t=0; t<this.routes.length; t++) {
var potentialRoute = this.routes[t],
pathRegExp = potentialRoute.path,
pathname = state.urlInfo.pathname,
match;
if(state.pathPrefix) {
@@ -248,7 +250,7 @@ Check whether a given user is authorized for the specified authorizationType ("r
Server.prototype.isAuthorized = function(authorizationType,username) {
var principals = this.authorizationPrincipals[authorizationType] || [];
return principals.indexOf("(anon)") !== -1 || (username && (principals.indexOf("(authenticated)") !== -1 || principals.indexOf(username) !== -1));
}
};
Server.prototype.requestHandler = function(request,response,options) {
options = options || {};
@@ -261,6 +263,13 @@ Server.prototype.requestHandler = function(request,response,options) {
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
// Enable CORS
if(this.corsEnable) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Expose-Headers", "*");
}
state.sendResponse = sendResponse.bind(self,request,response);
// Get the principals authorized to access this resource
state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers";
@@ -285,6 +294,12 @@ Server.prototype.requestHandler = function(request,response,options) {
response.end();
return;
}
// Reply to OPTIONS
if(this.corsEnable && request.method === "OPTIONS") {
response.writeHead(204);
response.end();
return;
}
// Find the route that matches this path
var route = self.findMatchingRoute(request,state);
// Optionally output debug info
@@ -322,7 +337,7 @@ Server.prototype.requestHandler = function(request,response,options) {
request.on("end",function() {
state.data = Buffer.concat(data);
route.handler(request,response,state);
})
});
} else {
response.writeHead(400,"Invalid bodyFormat " + route.bodyFormat + " in route " + route.method + " " + route.path.source);
response.end();
@@ -347,8 +362,8 @@ Server.prototype.listen = function(port,host,prefix) {
}
// Warn if required plugins are missing
var missing = [];
for (var index=0; index<this.requiredPlugins.length; index++) {
if (!this.wiki.getTiddler(this.requiredPlugins[index])) {
for(var index=0; index<this.requiredPlugins.length; index++) {
if(!this.wiki.getTiddler(this.requiredPlugins[index])) {
missing.push(this.requiredPlugins[index]);
}
}

View File

@@ -9,22 +9,22 @@ Base64 UTF-8 utlity functions.
"use strict";
const{ TextEncoder, TextDecoder } = require("node:util");
const { TextEncoder, TextDecoder } = require("node:util");
exports.btoa = binstr => Buffer.from(binstr, "binary").toString("base64");
exports.btoa = (binstr) => Buffer.from(binstr, "binary").toString("base64");
exports.atob = b64 => Buffer.from(b64, "base64").toString("binary");
exports.atob = (b64) => Buffer.from(b64, "base64").toString("binary");
function base64ToBytes(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, m => m.codePointAt(0));
return Uint8Array.from(binString, (m) => m.codePointAt(0));
};
function bytesToBase64(bytes) {
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
exports.base64EncodeUtf8 = (str) => bytesToBase64(new TextEncoder().encode(str));
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));
exports.base64DecodeUtf8 = (str) => new TextDecoder().decode(base64ToBytes(str));

View File

@@ -16,8 +16,7 @@ ignoreEnvironmentVariables: defaults to false
*/
exports.getAllPlugins = function(options) {
options = options || {};
var fs = require("fs"),
path = require("path"),
var path = require("path"),
tiddlers = {};
// Collect up the library plugins
var collectPlugins = function(folder) {

View File

@@ -6,6 +6,7 @@ Appearance/Caption: Appearance
Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
Basics/AnimDuration/Prompt: Animation duration
Basics/AutoFocus/Prompt: Default focus field for new tiddlers
Basics/AutoFocusEdit/Prompt: Default focus field for existing tiddlers
Basics/Caption: Basics
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/Prompt: Default tiddlers

View File

@@ -0,0 +1,4 @@
title: $:/language/Draft/
Attribution: Draft of '<<draft-title>>' by {{$:/status/UserName}}
Title: Draft of '<<draft-title>>'

View File

@@ -9,6 +9,11 @@ Advanced/ShadowInfo/NotShadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text
Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler
Advanced/ShadowInfo/Shadow/Source: It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>
Advanced/ShadowInfo/OverriddenShadow/Hint: It is overridden by an ordinary tiddler
Advanced/CascadeInfo/Heading: Cascade Details
Advanced/CascadeInfo/Hint: These are the view template segments (tagged <<tag "$:/tags/ViewTemplate">>) using a cascade filter and their resulting template for the current tiddler.
Advanced/CascadeInfo/Detail/View: View
Advanced/CascadeInfo/Detail/ActiveCascadeFilter: Active cascade filter
Advanced/CascadeInfo/Detail/Template: Template
Fields/Caption: Fields
List/Caption: List
List/Empty: This tiddler does not have a list

View File

@@ -0,0 +1,116 @@
/*\
title: $:/core/modules/background-actions.js
type: application/javascript
module-type: global
Class to dispatch actions when filters change
\*/
"use strict";
class BackgroundActionDispatcher {
constructor(filterTracker, wiki) {
this.filterTracker = filterTracker;
this.wiki = wiki;
this.nextTrackedFilterId = 1;
this.trackedFilters = new Map(); // Use Map for better key management
// Track the filter for the background actions
this.filterTracker.track({
filterString: "[all[tiddlers+shadows]tag[$:/tags/BackgroundAction]!is[draft]]",
fnEnter: (title) => this.trackFilter(title),
fnLeave: (title, enterValue) => this.untrackFilter(enterValue),
fnChange: (title, enterValue) => {
this.untrackFilter(enterValue);
return this.trackFilter(title);
},
fnProcess: (changes) => this.process(changes)
});
}
trackFilter(title) {
const tiddler = this.wiki.getTiddler(title);
const id = this.nextTrackedFilterId++;
const tracker = new BackgroundActionTracker({
wiki: this.wiki,
title,
trackFilter: tiddler.fields["track-filter"],
actions: tiddler.fields.text
});
this.trackedFilters.set(id, tracker);
return id;
}
untrackFilter(enterValue) {
const tracker = this.trackedFilters.get(enterValue);
if(tracker) {
tracker.destroy();
}
this.trackedFilters.delete(enterValue);
}
process(changes) {
for(const tracker of this.trackedFilters.values()) {
tracker.process(changes);
}
}
}
/*
Represents an individual tracked filter. Options include:
wiki: wiki to use
title: title of the tiddler being tracked
trackFilter: filter string to track changes
actions: actions to be executed when the filter changes
*/
class BackgroundActionTracker {
constructor({wiki, title, trackFilter, actions}) {
this.wiki = wiki;
this.title = title;
this.trackFilter = trackFilter;
this.actions = actions;
this.filterTracker = new $tw.FilterTracker(this.wiki);
this.hasChanged = false;
this.trackerID = this.filterTracker.track({
filterString: this.trackFilter,
fnEnter: () => { this.hasChanged = true; },
fnLeave: () => { this.hasChanged = true; },
fnProcess: (changes) => {
if(this.hasChanged) {
this.hasChanged = false;
console.log("Processing background action", this.title);
const tiddler = this.wiki.getTiddler(this.title);
let doActions = true;
if(tiddler && tiddler.fields.platforms) {
doActions = false;
const platforms = $tw.utils.parseStringArray(tiddler.fields.platforms);
if(($tw.browser && platforms.includes("browser")) || ($tw.node && platforms.includes("node"))) {
doActions = true;
}
}
if(doActions) {
this.wiki.invokeActionString(
this.actions,
null,
{
currentTiddler: this.title
},{
parentWidget: $tw.rootWidget
}
);
}
}
}
});
}
process(changes) {
this.filterTracker.handleChangeEvent(changes);
}
destroy() {
this.filterTracker.untrack(this.trackerID);
}
}
exports.BackgroundActionDispatcher = BackgroundActionDispatcher;

View File

@@ -197,7 +197,7 @@ FramedEngine.prototype.handleFocusEvent = function(event) {
Handle a keydown event
*/
FramedEngine.prototype.handleKeydownEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
if($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
}

View File

@@ -48,19 +48,19 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.toolbarNode = this.document.createElement("div");
this.toolbarNode.className = "tc-editor-toolbar";
parent.insertBefore(this.toolbarNode,nextSibling);
this.renderChildren(this.toolbarNode,null);
this.domNodes.push(this.toolbarNode);
this.renderChildren(this.toolbarNode,null);
}
// Create our element
var editInfo = this.getEditInfo(),
Engine = this.editShowToolbar ? toolbarEngine : nonToolbarEngine;
this.engine = new Engine({
widget: this,
value: editInfo.value,
type: editInfo.type,
parentNode: parent,
nextSibling: nextSibling
});
widget: this,
value: editInfo.value,
type: editInfo.type,
parentNode: parent,
nextSibling: nextSibling
});
// Call the postRender hook
if(this.postRender) {
this.postRender();
@@ -220,7 +220,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
} else if(changedTiddlers[this.editRefreshTitle]) {
this.engine.updateDomNodeText(this.getEditInfo().value);
} else if(changedTiddlers[this.editTitle]) {
var editInfo = this.getEditInfo();
@@ -274,8 +274,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
});
if($tw.keyboardManager.checkKeyDescriptors(event,keyInfoArray)) {
var clickEvent = this.document.createEvent("Events");
clickEvent.initEvent("click",true,false);
el.dispatchEvent(clickEvent);
clickEvent.initEvent("click",true,false);
el.dispatchEvent(clickEvent);
event.preventDefault();
event.stopPropagation();
return true;

View File

@@ -10,7 +10,7 @@ Text editor operation to excise the selection to a new tiddler
"use strict";
function isMarkdown(mediaType) {
return mediaType === 'text/markdown' || mediaType === 'text/x-markdown';
return mediaType === "text/markdown" || mediaType === "text/x-markdown";
}
exports["excise"] = function(event,operation) {

View File

@@ -19,7 +19,7 @@ exports["wrap-lines"] = function(event,operation) {
operation.cutStart = operation.selStart - (prefix.length + 1);
operation.cutEnd = operation.selEnd + suffix.length + 1;
// Also cut the following newline (if there is any)
if (operation.text[operation.cutEnd] === "\n") {
if(operation.text[operation.cutEnd] === "\n") {
operation.cutEnd++;
}
// Replace with selection

View File

@@ -44,7 +44,7 @@ exports["wrap-selection"] = function(event,operation) {
break;
}
return result;
}
};
function togglePrefixSuffix() {
if(o.text.substring(o.selStart - prefix.length, o.selStart + suffix.length) === prefix + suffix) {

View File

@@ -0,0 +1,106 @@
/*\
title: $:/core/modules/filter-tracker.js
type: application/javascript
module-type: global
Class to track the results of a filter string
\*/
"use strict";
class FilterTracker {
constructor(wiki) {
this.wiki = wiki;
this.trackers = new Map();
this.nextTrackerId = 1;
}
handleChangeEvent(changes) {
this.processTrackers();
this.processChanges(changes);
}
/*
Add a tracker to the filter tracker. Returns null if any of the parameters are invalid, or a tracker id if the tracker was added successfully. Options include:
filterString: the filter string to track
fnEnter: function to call when a title enters the filter results. Called even if the tiddler does not actually exist. Called as (title), and should return a truthy value that is stored in the tracker as the "enterValue"
fnLeave: function to call when a title leaves the filter results. Called as (title,enterValue)
fnChange: function to call when a tiddler changes in the filter results. Only called for filter results that identify a tiddler or shadow tiddler. Called as (title,enterValue), and may optionally return a replacement enterValue
fnProcess: function to call each time the tracker is processed, after any enter, leave or change functions are called. Called as (changes)
*/
track(options = {}) {
const {
filterString,
fnEnter,
fnLeave,
fnChange,
fnProcess
} = options;
const id = this.nextTrackerId++;
const tracker = {
id,
filterString,
fnEnter,
fnLeave,
fnChange,
fnProcess,
previousResults: [],
resultValues: {}
};
this.trackers.set(id, tracker);
// Process the tracker
this.processTracker(id);
return id;
}
untrack(id) {
this.trackers.delete(id);
}
processTrackers() {
for(const id of this.trackers.keys()) {
this.processTracker(id);
}
}
processTracker(id) {
const tracker = this.trackers.get(id);
if(!tracker) return;
const results = [];
// Evaluate the filter and remove duplicate results
$tw.utils.each(this.wiki.filterTiddlers(tracker.filterString), (title) => {
$tw.utils.pushTop(results, title);
});
// Process the newly entered results
results.forEach((title) => {
if(!tracker.previousResults.includes(title) && !tracker.resultValues[title] && tracker.fnEnter) {
tracker.resultValues[title] = tracker.fnEnter(title) || true;
}
});
// Process the results that have just left
tracker.previousResults.forEach((title) => {
if(!results.includes(title) && tracker.resultValues[title] && tracker.fnLeave) {
tracker.fnLeave(title, tracker.resultValues[title]);
delete tracker.resultValues[title];
}
});
// Update the previous results
tracker.previousResults = results;
}
processChanges(changes) {
for(const tracker of this.trackers.values()) {
Object.keys(changes).forEach((title) => {
if(title && tracker.previousResults.includes(title) && tracker.fnChange) {
tracker.resultValues[title] = tracker.fnChange(title, tracker.resultValues[title]) || tracker.resultValues[title];
}
});
if(tracker.fnProcess) {
tracker.fnProcess(changes);
}
}
}
}
exports.FilterTracker = FilterTracker;

View File

@@ -24,7 +24,7 @@ exports.cascade = function(operationSubFunction,options) {
}
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler","")
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
}));
if(output.length !== 0) {
result = output[0];
@@ -34,5 +34,5 @@ exports.cascade = function(operationSubFunction,options) {
results.push(result);
});
}
}
};
};

View File

@@ -18,7 +18,7 @@ exports.filter = function(operationSubFunction,options) {
results.each(function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""),
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
@@ -30,5 +30,5 @@ exports.filter = function(operationSubFunction,options) {
});
results.remove(resultsToRemove);
}
}
};
};

View File

@@ -7,8 +7,6 @@ Assign a value to a variable
\*/
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*

View File

@@ -20,7 +20,7 @@ exports.map = function(operationSubFunction,options) {
$tw.utils.each(inputTitles,function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""),
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length
@@ -28,12 +28,12 @@ exports.map = function(operationSubFunction,options) {
if(filtered.length && flatten) {
$tw.utils.each(filtered,function(value) {
results.push(value);
})
});
} else {
results.push(filtered[0]||"");
}
++index;
});
}
}
};
};

View File

@@ -17,7 +17,7 @@ exports.reduce = function(operationSubFunction,options) {
results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length,
@@ -31,5 +31,5 @@ exports.reduce = function(operationSubFunction,options) {
results.clear();
results.push(accumulator);
}
}
};
};

View File

@@ -24,7 +24,7 @@ exports.sort = function(operationSubFunction,options) {
results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
}));
sortKeys.push(key[0] || "");
});
@@ -36,12 +36,12 @@ exports.sort = function(operationSubFunction,options) {
// Sort the indexes
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
return compareFn(sortKeys[a],sortKeys[b]);
});
// Add to results in correct order
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
}
}
};
};

View File

@@ -43,7 +43,7 @@ function parseFilterOperation(operators,filterString,p) {
var bracket = filterString.charAt(nextBracketPos);
operator.operator = filterString.substring(p,nextBracketPos);
// Any suffix?
var colon = operator.operator.indexOf(':');
var colon = operator.operator.indexOf(":");
if(colon > -1) {
// The raw suffix for older filters
operator.suffix = operator.operator.substring(colon + 1);
@@ -67,7 +67,7 @@ function parseFilterOperation(operators,filterString,p) {
operator.operands = [];
var parseOperand = function(bracketType) {
var operand = {};
switch (bracketType) {
switch(bracketType) {
case "{": // Curly brackets
operand.indirect = true;
nextBracketPos = filterString.indexOf("}",p);
@@ -108,7 +108,7 @@ function parseFilterOperation(operators,filterString,p) {
}
operator.operands.push(operand);
p = nextBracketPos + 1;
}
};
p = nextBracketPos + 1;
parseOperand(bracket);
@@ -228,16 +228,11 @@ exports.getFilterRunPrefixes = function() {
$tw.modules.applyMethods("filterrunprefix",this.filterRunPrefixes);
}
return this.filterRunPrefixes;
}
};
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
try {
const fnResult = fn.call(this,source,widget);
return fnResult;
} catch(e) {
return [`${$tw.language.getString("Error/Filter")}: ${e}`];
}
return fn.call(this,source,widget);
};
/*

View File

@@ -32,4 +32,4 @@ var modes = {
"gt": function(value) {return value > 0;},
"lteq": function(value) {return value <= 0;},
"lt": function(value) {return value < 0;}
}
};

View File

@@ -31,4 +31,4 @@ exports["deserialize"] = function(source,operator,options) {
return [$tw.language.getString("Error/DeserializeOperator/MissingOperand")];
}
return results;
}
};

View File

@@ -15,8 +15,8 @@ Export our filter function
*/
exports.each = function(source,operator,options) {
var results =[] ,
value,values = {},
field = operator.operand || "title";
value,values = {},
field = operator.operand || "title";
if(operator.suffix === "value" && field === "title") {
source(function(tiddler,title) {
if(!$tw.utils.hop(values,title)) {

View File

@@ -53,7 +53,7 @@ exports.field = function(source,operator,options) {
if(source.byField && operator.operand) {
indexedResults = source.byField(fieldname,operator.operand);
if(indexedResults) {
return indexedResults
return indexedResults;
}
}
source(function(tiddler,title) {

View File

@@ -24,7 +24,7 @@ exports.fields = function(source,operator,options) {
for(fieldName in tiddler.fields) {
(operand.indexOf(fieldName) !== -1) ? $tw.utils.pushTop(results,fieldName) : "";
}
} else if (suffixes.indexOf("exclude") !== -1) {
} else if(suffixes.indexOf("exclude") !== -1) {
for(fieldName in tiddler.fields) {
(operand.indexOf(fieldName) !== -1) ? "" : $tw.utils.pushTop(results,fieldName);
}

View File

@@ -19,7 +19,7 @@ exports.filter = function(source,operator,options) {
source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler","")
"..currentTiddler": options.widget.getVariable("currentTiddler",{defaultValue:""})
}));
if((list.length > 0) === target) {
results.push(title);

View File

@@ -12,7 +12,7 @@ Export our filter function
exports.timestamp = function(source,operand,options) {
var results = [];
source(function(tiddler,title) {
if (title.match(/^-?\d+$/)) {
if(title.match(/^-?\d+$/)) {
var value = new Date(Number(title));
results.push($tw.utils.formatDateString(value,operand || "[UTC]YYYY0MM0DD0hh0mm0ss0XXX"));
}

View File

@@ -13,7 +13,7 @@ returns the value at a given index of datatiddlers
Export our filter function
*/
exports.getindex = function(source,operator,options) {
var data,title,results = [];
var data,results = [];
if(operator.operand){
source(function(tiddler,title) {
title = tiddler ? tiddler.fields.title : title;

View File

@@ -157,13 +157,13 @@ function convertDataItemValueToStrings(item) {
if(item === undefined) {
return undefined;
} else if(item === null) {
return ["null"]
return ["null"];
} else if(typeof item === "object") {
var results = [],i,t;
if(Array.isArray(item)) {
// Return all the items in arrays recursively
for(i=0; i<item.length; i++) {
t = convertDataItemValueToStrings(item[i])
t = convertDataItemValueToStrings(item[i]);
if(t !== undefined) {
results.push.apply(results,t);
}
@@ -231,7 +231,7 @@ function getItemAtIndex(item,index) {
return item[index];
} else if(Array.isArray(item)) {
index = $tw.utils.parseInt(index);
if(index < 0) { index = index + item.length };
if(index < 0) { index = index + item.length; };
return item[index]; // Will be undefined if index was out-of-bounds
} else {
return undefined;
@@ -289,7 +289,7 @@ function setDataItem(data,indexes,value) {
var lastIndex = indexes[indexes.length - 1];
if(Array.isArray(current)) {
lastIndex = $tw.utils.parseInt(lastIndex);
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
if(lastIndex < 0) { lastIndex = lastIndex + current.length; };
}
// Only set indexes on objects and arrays
if(typeof current === "object") {
@@ -316,7 +316,7 @@ function deleteDataItem(data,indexes) {
var lastIndex = indexes[indexes.length - 1];
if(Array.isArray(current) && current !== null) {
lastIndex = $tw.utils.parseInt(lastIndex);
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
if(lastIndex < 0) { lastIndex = lastIndex + current.length; };
// Check if index is valid before splicing
if(lastIndex >= 0 && lastIndex < current.length) {
current.splice(lastIndex,1);

View File

@@ -25,7 +25,7 @@ exports.lookup = function(source,operator,options) {
indexSuffix = (suffixes[1] && suffixes[1][0] === "index") ? true : false,
target;
if(operator.operands.length == 2) {
target = operator.operands[1]
target = operator.operands[1];
} else {
target = indexSuffix ? "0": "text";
}

View File

@@ -17,35 +17,35 @@ Note that strings are converted to numbers automatically. Trailing non-digits ar
"use strict";
exports.negate = makeNumericBinaryOperator(
function(a) {return -a}
function(a) {return -a;}
);
exports.abs = makeNumericBinaryOperator(
function(a) {return Math.abs(a)}
function(a) {return Math.abs(a);}
);
exports.ceil = makeNumericBinaryOperator(
function(a) {return Math.ceil(a)}
function(a) {return Math.ceil(a);}
);
exports.floor = makeNumericBinaryOperator(
function(a) {return Math.floor(a)}
function(a) {return Math.floor(a);}
);
exports.round = makeNumericBinaryOperator(
function(a) {return Math.round(a)}
function(a) {return Math.round(a);}
);
exports.trunc = makeNumericBinaryOperator(
function(a) {return Math.trunc(a)}
function(a) {return Math.trunc(a);}
);
exports.untrunc = makeNumericBinaryOperator(
function(a) {return Math.ceil(Math.abs(a)) * Math.sign(a)}
function(a) {return Math.ceil(Math.abs(a)) * Math.sign(a);}
);
exports.sign = makeNumericBinaryOperator(
function(a) {return Math.sign(a)}
function(a) {return Math.sign(a);}
);
exports.add = makeNumericBinaryOperator(
@@ -103,29 +103,29 @@ exports.log = makeNumericBinaryOperator(
);
exports.sum = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
function(accumulator,value) {return accumulator + value;},
0 // Initial value
);
exports.product = makeNumericReducingOperator(
function(accumulator,value) {return accumulator * value},
function(accumulator,value) {return accumulator * value;},
1 // Initial value
);
exports.maxall = makeNumericReducingOperator(
function(accumulator,value) {return Math.max(accumulator,value)},
function(accumulator,value) {return Math.max(accumulator,value);},
-Infinity // Initial value
);
exports.minall = makeNumericReducingOperator(
function(accumulator,value) {return Math.min(accumulator,value)},
function(accumulator,value) {return Math.min(accumulator,value);},
Infinity // Initial value
);
exports.median = makeNumericArrayOperator(
function(values) {
var len = values.length, median;
values.sort(function(a,b) {return a-b});
values.sort(function(a,b) {return a-b;});
if(len % 2) {
// Odd, return the middle number
median = values[(len - 1) / 2];
@@ -138,7 +138,7 @@ exports.median = makeNumericArrayOperator(
);
exports.average = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
function(accumulator,value) {return accumulator + value;},
0, // Initial value
function(finalValue,numberOfValues) {
return finalValue/numberOfValues;
@@ -146,7 +146,7 @@ exports.average = makeNumericReducingOperator(
);
exports.variance = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
function(accumulator,value) {return accumulator + value;},
0,
function(finalValue,numberOfValues,originalValues) {
return getVarianceFromArray(originalValues,finalValue/numberOfValues);
@@ -154,7 +154,7 @@ exports.variance = makeNumericReducingOperator(
);
exports["standard-deviation"] = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
function(accumulator,value) {return accumulator + value;},
0,
function(finalValue,numberOfValues,originalValues) {
var variance = getVarianceFromArray(originalValues,finalValue/numberOfValues);
@@ -164,31 +164,31 @@ exports["standard-deviation"] = makeNumericReducingOperator(
//trigonometry
exports.cos = makeNumericBinaryOperator(
function(a) {return Math.cos(a)}
function(a) {return Math.cos(a);}
);
exports.sin = makeNumericBinaryOperator(
function(a) {return Math.sin(a)}
function(a) {return Math.sin(a);}
);
exports.tan = makeNumericBinaryOperator(
function(a) {return Math.tan(a)}
function(a) {return Math.tan(a);}
);
exports.acos = makeNumericBinaryOperator(
function(a) {return Math.acos(a)}
function(a) {return Math.acos(a);}
);
exports.asin = makeNumericBinaryOperator(
function(a) {return Math.asin(a)}
function(a) {return Math.asin(a);}
);
exports.atan = makeNumericBinaryOperator(
function(a) {return Math.atan(a)}
function(a) {return Math.atan(a);}
);
exports.atan2 = makeNumericBinaryOperator(
function(a,b) {return Math.atan2(a,b)}
function(a,b) {return Math.atan2(a,b);}
);
//Calculate the variance of a population of numbers in an array given its mean
@@ -222,8 +222,8 @@ function makeNumericReducingOperator(fnCalc,initialValue,fnFinal) {
return [];
}
var value = result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,currentValue);
},initialValue);
return fnCalc(accumulator,currentValue);
},initialValue);
if(fnFinal) {
value = fnFinal(value,result.length,result);
}

View File

@@ -21,7 +21,7 @@ exports.range = function(source,operator,options) {
}
// Process the parts
var beg, end, inc, i, fixed = 0;
for (i=0; i<parts.length; i++) {
for(i=0; i<parts.length; i++) {
// Validate real number
if(!/^\s*[+-]?((\d+(\.\d*)?)|(\.\d+))\s*$/.test(parts[i])) {
return ["range: bad number \"" + parts[i] + "\""];
@@ -36,10 +36,10 @@ exports.range = function(source,operator,options) {
switch(parts.length) {
case 1:
end = parts[0];
if (end >= 1) {
if(end >= 1) {
beg = 1;
}
else if (end <= -1) {
else if(end <= -1) {
beg = -1;
}
else {
@@ -72,7 +72,7 @@ exports.range = function(source,operator,options) {
end += direction * 0.5 * Math.pow(0.1,fixed);
var safety = 10010;
// Enumerate the range
if (end<beg) {
if(end<beg) {
for(i=beg; i>end; i+=inc) {
results.push(i.toFixed(fixed));
if(--safety<0) {

View File

@@ -15,7 +15,7 @@ Export our filter function
exports.removesuffix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if (!operator.operand) {
if(!operator.operand) {
source(function(tiddler,title) {
results.push(title);
});

View File

@@ -15,7 +15,7 @@ Export our filter function
exports.suffix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if (!operator.operand) {
if(!operator.operand) {
source(function(tiddler,title) {
results.push(title);
});

View File

@@ -24,4 +24,4 @@ exports.variables = function(source,operator,options) {
}
}
return names.sort();
};
};

View File

@@ -7,224 +7,224 @@ Extended filter operators to manipulate the current list.
\*/
"use strict";
"use strict";
/*
/*
Fetch titles from the current list
*/
var prepare_results = function (source) {
var prepare_results = function (source) {
var results = [];
source(function (tiddler, title) {
results.push(title);
});
return results;
};
source(function (tiddler, title) {
results.push(title);
});
return results;
};
/*
/*
Moves a number of items from the tail of the current list before the item named in the operand
*/
exports.putbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
};
exports.putbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
};
/*
/*
Moves a number of items from the tail of the current list after the item named in the operand
*/
exports.putafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
exports.putafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
/*
Replaces the item named in the operand with a number of items from the tail of the current list
*/
exports.replace = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -count) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
exports.replace = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -count) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
/*
Moves a number of items from the tail of the current list to the head of the list
*/
exports.putfirst = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(-count).concat(results.slice(0, -count));
};
exports.putfirst = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(-count).concat(results.slice(0, -count));
};
/*
/*
Moves a number of items from the head of the current list to the tail of the list
*/
exports.putlast = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(count).concat(results.slice(0, count));
};
exports.putlast = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(count).concat(results.slice(0, count));
};
/*
/*
Moves the item named in the operand a number of places forward or backward in the list
*/
exports.move = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1),
marker = results.splice(index, 1),
offset = (index + count) > 0 ? index + count : 0;
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
};
exports.move = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1),
marker = results.splice(index, 1),
offset = (index + count) > 0 ? index + count : 0;
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
};
/*
/*
Returns the items from the current list that are after the item named in the operand
*/
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
results.slice(index + 1);
};
};
/*
/*
Returns the items from the current list that are before the item named in the operand
*/
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
results.slice(0, index);
};
};
/*
/*
Appends the items listed in the operand array to the tail of the current list
*/
exports.append = function (source, operator) {
var append = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || append.length;
return (append.length === 0) ? results :
(operator.prefix) ? results.concat(append.slice(-count)) :
exports.append = function (source, operator) {
var append = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || append.length;
return (append.length === 0) ? results :
(operator.prefix) ? results.concat(append.slice(-count)) :
results.concat(append.slice(0, count));
};
};
/*
/*
Prepends the items listed in the operand array to the head of the current list
*/
exports.prepend = function (source, operator) {
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,prepend.length);
return (prepend.length === 0) ? results :
(operator.prefix) ? prepend.slice(-count).concat(results) :
exports.prepend = function (source, operator) {
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,prepend.length);
return (prepend.length === 0) ? results :
(operator.prefix) ? prepend.slice(-count).concat(results) :
prepend.slice(0, count).concat(results);
};
};
/*
/*
Returns all items from the current list except the items listed in the operand array
*/
exports.remove = function (source, operator) {
var array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || array.length,
p,
len,
index;
len = array.length - 1;
for (p = 0; p < count; ++p) {
if (operator.prefix) {
index = results.indexOf(array[len - p]);
} else {
index = results.indexOf(array[p]);
}
if (index !== -1) {
results.splice(index, 1);
}
exports.remove = function (source, operator) {
var array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || array.length,
p,
len,
index;
len = array.length - 1;
for(p = 0; p < count; ++p) {
if(operator.prefix) {
index = results.indexOf(array[len - p]);
} else {
index = results.indexOf(array[p]);
}
return results;
};
if(index !== -1) {
results.splice(index, 1);
}
}
return results;
};
/*
/*
Returns all items from the current list sorted in the order of the items in the operand array
*/
exports.sortby = function (source, operator) {
var results = prepare_results(source);
if (!results || results.length < 2) {
return results;
}
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
results.sort(function (a, b) {
return lookup.indexOf(a) - lookup.indexOf(b);
});
exports.sortby = function (source, operator) {
var results = prepare_results(source);
if(!results || results.length < 2) {
return results;
};
}
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
results.sort(function (a, b) {
return lookup.indexOf(a) - lookup.indexOf(b);
});
return results;
};
/*
/*
Removes all duplicate items from the current list
*/
exports.unique = function (source, operator) {
var results = prepare_results(source);
var set = results.reduce(function (a, b) {
if (a.indexOf(b) < 0) {
a.push(b);
}
return a;
}, []);
return set;
};
var cycleValueInArray = function(results,operands,stepSize) {
var resultsIndex,
step = stepSize || 1,
i = 0,
opLength = operands.length,
nextOperandIndex;
for(i; i < opLength; i++) {
resultsIndex = results.indexOf(operands[i]);
if(resultsIndex !== -1) {
break;
}
exports.unique = function (source, operator) {
var results = prepare_results(source);
var set = results.reduce(function (a, b) {
if(a.indexOf(b) < 0) {
a.push(b);
}
return a;
}, []);
return set;
};
var cycleValueInArray = function(results,operands,stepSize) {
var resultsIndex,
step = stepSize || 1,
i = 0,
opLength = operands.length,
nextOperandIndex;
for(i; i < opLength; i++) {
resultsIndex = results.indexOf(operands[i]);
if(resultsIndex !== -1) {
i = i + step;
nextOperandIndex = (i < opLength ? i : i % opLength);
if(operands.length > 1) {
results.splice(resultsIndex,1,operands[nextOperandIndex]);
} else {
results.splice(resultsIndex,1);
}
} else {
results.push(operands[0]);
break;
}
return results;
}
if(resultsIndex !== -1) {
i = i + step;
nextOperandIndex = (i < opLength ? i : i % opLength);
if(operands.length > 1) {
results.splice(resultsIndex,1,operands[nextOperandIndex]);
} else {
results.splice(resultsIndex,1);
}
} else {
results.push(operands[0]);
}
return results;
};
/*
/*
Toggles an item in the current list.
*/
exports.toggle = function(source,operator) {
return cycleValueInArray(prepare_results(source),operator.operands);
}
exports.toggle = function(source,operator) {
return cycleValueInArray(prepare_results(source),operator.operands);
};
exports.cycle = function(source,operator) {
var results = prepare_results(source),
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
step = $tw.utils.getInt(operator.operands[1]||"",1);
if(step < 0) {
operands.reverse();
step = Math.abs(step);
}
return cycleValueInArray(results,operands,step);
exports.cycle = function(source,operator) {
var results = prepare_results(source),
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
step = $tw.utils.getInt(operator.operands[1]||"",1);
if(step < 0) {
operands.reverse();
step = Math.abs(step);
}
return cycleValueInArray(results,operands,step);
};

View File

@@ -46,7 +46,7 @@ function BackSubIndexer(indexer,extractor) {
BackSubIndexer.prototype.init = function() {
// lazy init until first lookup
this.index = null;
}
};
BackSubIndexer.prototype._init = function() {
this.index = Object.create(null);
@@ -60,11 +60,11 @@ BackSubIndexer.prototype._init = function() {
self.index[target][sourceTitle] = true;
});
});
}
};
BackSubIndexer.prototype.rebuild = function() {
this.index = null;
}
};
/*
* Get things that is being referenced in the text, e.g. tiddler names in the link syntax.
@@ -78,7 +78,7 @@ BackSubIndexer.prototype._getTarget = function(tiddler) {
return this.wiki[this.extractor](parser.tree, tiddler.fields.title);
}
return [];
}
};
BackSubIndexer.prototype.update = function(updateDescriptor) {
// lazy init/update until first lookup
@@ -86,8 +86,8 @@ BackSubIndexer.prototype.update = function(updateDescriptor) {
return;
}
var newTargets = [],
oldTargets = [],
self = this;
oldTargets = [],
self = this;
if(updateDescriptor.old.exists) {
oldTargets = this._getTarget(updateDescriptor.old.tiddler);
}
@@ -106,7 +106,7 @@ BackSubIndexer.prototype.update = function(updateDescriptor) {
}
self.index[target][updateDescriptor.new.tiddler.fields.title] = true;
});
}
};
BackSubIndexer.prototype.lookup = function(title) {
if(!this.index) {
@@ -117,6 +117,6 @@ BackSubIndexer.prototype.lookup = function(title) {
} else {
return [];
}
}
};
exports.BackIndexer = BackIndexer;

View File

@@ -19,7 +19,7 @@ FieldIndexer.prototype.init = function() {
this.index = null;
this.maxIndexedValueLength = DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH;
this.addIndexMethods();
}
};
// Provided for testing
FieldIndexer.prototype.setMaxIndexedValueLength = function(length) {
@@ -33,14 +33,14 @@ FieldIndexer.prototype.addIndexMethods = function() {
this.wiki.each.byField = function(name,value) {
var lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return self.wiki.tiddlerExists(title)
return self.wiki.tiddlerExists(title);
});
};
// get shadow tiddlers, including shadow tiddlers that is overwritten
this.wiki.eachShadow.byField = function(name,value) {
var lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return self.wiki.isShadowTiddler(title)
return self.wiki.isShadowTiddler(title);
});
};
this.wiki.eachTiddlerPlusShadows.byField = function(name,value) {

View File

@@ -14,12 +14,12 @@ exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
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]
["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]
];
}

View File

@@ -0,0 +1,67 @@
/*\
title: $:/core/modules/info/mediaquerytracker.js
type: application/javascript
module-type: info
Initialise $:/info/ tiddlers derived from media queries via
\*/
"use strict";
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
if($tw.browser) {
// Functions to start and stop tracking a particular media query tracker tiddler
function track(title) {
var result = {},
tiddler = $tw.wiki.getTiddler(title);
if(tiddler) {
var mediaQuery = tiddler.fields["media-query"],
infoTiddler = tiddler.fields["info-tiddler"],
infoTiddlerAlt = tiddler.fields["info-tiddler-alt"];
if(mediaQuery && infoTiddler) {
// Evaluate and track the media query
result.mqList = window.matchMedia(mediaQuery);
function getResultTiddlers() {
var value = result.mqList.matches ? "yes" : "no",
tiddlers = [];
tiddlers.push({title: infoTiddler, text: value});
if(infoTiddlerAlt) {
tiddlers.push({title: infoTiddlerAlt, text: value});
}
return tiddlers;
};
updateInfoTiddlersCallback(getResultTiddlers());
result.handler = function(event) {
updateInfoTiddlersCallback(getResultTiddlers());
};
result.mqList.addEventListener("change",result.handler);
}
}
return result;
}
function untrack(enterValue) {
if(enterValue.mqList && enterValue.handler) {
enterValue.mqList.removeEventListener("change",enterValue.handler);
}
}
// Track media query tracker tiddlers
function fnEnter(title) {
return track(title);
}
function fnLeave(title,enterValue) {
untrack(enterValue);
}
function fnChange(title,enterValue) {
untrack(enterValue);
return track(title);
}
$tw.filterTracker.track({
filterString: "[all[tiddlers+shadows]tag[$:/tags/MediaQueryTracker]!is[draft]]",
fnEnter: fnEnter,
fnLeave: fnLeave,
fnChange: fnChange
});
}
return [];
};

View File

@@ -33,13 +33,6 @@ exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
// Screen size
infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()});
infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()});
// Dark mode through event listener on MediaQueryList
var mqList = window.matchMedia("(prefers-color-scheme: dark)"),
getDarkModeTiddler = function() {return {title: "$:/info/darkmode", text: mqList.matches ? "yes" : "no"};};
infoTiddlerFields.push(getDarkModeTiddler());
mqList.addListener(function(event) {
updateInfoTiddlersCallback([getDarkModeTiddler()]);
});
// Language
infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""});
}

View File

@@ -140,7 +140,7 @@ function KeyboardManager(options) {
this.shortcutParsedList = []; // Stores the parsed key descriptors
this.shortcutPriorityList = []; // Stores the parsed shortcut priority
this.lookupNames = ["shortcuts"];
this.lookupNames.push($tw.platform.isMac ? "shortcuts-mac" : "shortcuts-not-mac")
this.lookupNames.push($tw.platform.isMac ? "shortcuts-mac" : "shortcuts-not-mac");
this.lookupNames.push($tw.platform.isWindows ? "shortcuts-windows" : "shortcuts-not-windows");
this.lookupNames.push($tw.platform.isLinux ? "shortcuts-linux" : "shortcuts-not-linux");
this.updateShortcutLists(this.getShortcutTiddlerList());
@@ -161,7 +161,7 @@ KeyboardManager.prototype.getModifierKeys = function() {
91, // Meta (left)
93, // Meta (right)
224 // Meta (Firefox)
]
];
};
/*
@@ -187,8 +187,7 @@ KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
metaKey: false
};
for(var t=0; t<components.length; t++) {
var s = components[t].toLowerCase(),
c = s.charCodeAt(0);
var s = components[t].toLowerCase();
// Look for modifier keys
if(s === "ctrl") {
info.ctrlKey = true;
@@ -266,7 +265,7 @@ KeyboardManager.prototype.getPrintableShortcuts = function(keyInfoArray) {
}
});
return result;
}
};
KeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {
return keyInfo &&
@@ -293,15 +292,15 @@ KeyboardManager.prototype.getMatchingKeyDescriptor = function(event,keyInfoArray
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
return event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? "ctrl" :
event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey ? "shift" :
event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? "ctrl-shift" :
event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt" :
event.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt-shift" :
event.altKey && event.ctrlKey && !event.shiftKey && !event.metaKey ? "ctrl-alt" :
event.altKey && event.shiftKey && event.ctrlKey && !event.metaKey ? "ctrl-alt-shift" :
event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? "meta" :
event.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? "meta-ctrl" :
event.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? "meta-ctrl-shift" :
event.metaKey && event.ctrlKey && event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? "ctrl-shift" :
event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt" :
event.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt-shift" :
event.altKey && event.ctrlKey && !event.shiftKey && !event.metaKey ? "ctrl-alt" :
event.altKey && event.shiftKey && event.ctrlKey && !event.metaKey ? "ctrl-alt-shift" :
event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? "meta" :
event.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? "meta-ctrl" :
event.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? "meta-ctrl-shift" :
event.metaKey && event.ctrlKey && event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
};
KeyboardManager.prototype.getShortcutTiddlerList = function() {
@@ -371,8 +370,8 @@ KeyboardManager.prototype.handleShortcutChanges = function(changedTiddlers) {
var newList = this.getShortcutTiddlerList();
var hasChanged = $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers) ? true :
($tw.utils.hopArray(changedTiddlers,newList) ? true :
(this.detectNewShortcuts(changedTiddlers))
);
(this.detectNewShortcuts(changedTiddlers))
);
// Re-cache shortcuts if something changed
if(hasChanged) {
this.updateShortcutLists(newList);

View File

@@ -24,8 +24,7 @@ exports.params = [
Run the macro
*/
exports.run = function(filter,format) {
var self = this,
tiddlers = this.wiki.filterTiddlers(filter),
var tiddlers = this.wiki.filterTiddlers(filter),
tiddler,
fields = [],
t,f;
@@ -46,24 +45,24 @@ exports.run = function(filter,format) {
var p = fields.indexOf(value);
if(p !== -1) {
fields.splice(p,1);
fields.unshift(value)
fields.unshift(value);
}
});
// Output the column headings
var output = [], row = [];
fields.forEach(function(value) {
row.push(quoteAndEscape(value))
row.push(quoteAndEscape(value));
});
output.push(row.join(","));
// Output each tiddler
for(var t=0;t<tiddlers.length; t++) {
row = [];
tiddler = this.wiki.getTiddler(tiddlers[t]);
if(tiddler) {
for(f=0; f<fields.length; f++) {
row.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || "" : ""));
}
}
if(tiddler) {
for(f=0; f<fields.length; f++) {
row.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || "" : ""));
}
}
output.push(row.join(","));
}
return output.join("\n");

View File

@@ -31,8 +31,8 @@ exports.run = function(shortcuts,prefix,separator,suffix) {
}));
if(shortcutArray.length > 0) {
shortcutArray.sort(function(a,b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
})
return a.toLowerCase().localeCompare(b.toLowerCase());
});
return prefix + shortcutArray.join(separator) + suffix;
} else {
return "";

View File

@@ -7,19 +7,17 @@ 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
attributes: {
controls: {type: "string", value: "controls"},
style: {type: "string", value: "width: 100%; object-fit: contain"}
}
};
type: "element",
tag: "$audio", // Using $audio to enable widget interception
attributes: {
controls: {type: "string", value: "controls"},
style: {type: "string", value: "width: 100%; object-fit: contain"}
}
};
// Pass through source information
if(options._canonical_uri) {

View File

@@ -59,7 +59,7 @@ var BinaryParser = function(type,text,options) {
class: {type: "string", value: "tc-binary-warning"}
},
children: [warn, link]
}
};
this.tree = [element];
this.source = text;
this.type = type;

View File

@@ -45,7 +45,7 @@ var CsvParser = function(type,text,options) {
row.children.push({
"type": "element", "tag": tag, "children": [{
"type": "text",
"text": columns[column] || ''
"text": columns[column] || ""
}]
});
}

View File

@@ -45,7 +45,7 @@ exports.parseWhiteSpace = function(source,pos) {
type: "whitespace",
start: pos,
end: p
}
};
}
};
@@ -107,13 +107,14 @@ exports.parseStringLiteral = function(source,pos) {
type: "string",
start: pos
};
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')/g;
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/g;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
node.value = match[1] !== undefined ? match[1] :(
match[2] !== undefined ? match[2] : match[3]
);
match[2] !== undefined ? match[2] : (
match[3] !== undefined ? match[3] : match[4]
));
node.end = pos + match[0].length;
return node;
} else {
@@ -142,7 +143,14 @@ exports.parseParameterDefinition = function(paramString,options) {
var paramInfo = {name: paramMatch[1]},
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5];
if(defaultValue !== undefined) {
paramInfo["default"] = defaultValue;
// Check for an MVV reference ((varname))
var mvvDefaultMatch = /^\(\(([^)|]+)\)\)$/.exec(defaultValue);
if(mvvDefaultMatch) {
paramInfo.defaultType = "multivalue-variable";
paramInfo.defaultVariable = mvvDefaultMatch[1];
} else {
paramInfo["default"] = defaultValue;
}
}
params.push(paramInfo);
// Look for the next parameter
@@ -162,7 +170,7 @@ exports.parseMacroParameters = function(node,source,pos) {
}
node.end = pos;
return node;
}
};
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
@@ -173,7 +181,7 @@ exports.parseMacroParameter = function(source,pos) {
start: pos
};
// Define our regexp
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[((?:[^\]]|\](?!\]))*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the parameter
@@ -184,16 +192,16 @@ exports.parseMacroParameter = function(source,pos) {
pos = token.end;
// Get the parameter details
node.value = token.match[2] !== undefined ? token.match[2] : (
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
token.match[6] !== undefined ? token.match[6] : (
""
)
)
)
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
token.match[6] !== undefined ? token.match[6] : (
""
)
);
)
)
)
);
if(token.match[1]) {
node.name = token.match[1];
}
@@ -206,28 +214,201 @@ exports.parseMacroParameter = function(source,pos) {
Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:}
*/
exports.parseMacroInvocationAsTransclusion = function(source,pos) {
var node = $tw.utils.parseMacroInvocation(source,pos);
if(node) {
var positionalName = 0,
transclusion = {
type: "transclude",
start: node.start,
end: node.end
};
$tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name);
$tw.utils.each(node.params,function(param) {
var name = param.name;
if(name) {
if(name.charAt(0) === "$") {
name = "$" + name;
}
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end});
} else {
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end});
}
});
return transclusion;
var node = {
type: "transclude",
start: pos,
attributes: {},
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=:]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening angle bracket
var token = $tw.utils.parseTokenString(source,pos,"<<");
if(!token) {
return null;
}
pos = token.end;
// Get the variable name for the macro
token = $tw.utils.parseTokenRegExp(source,pos,reVarName);
if(!token) {
return null;
}
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
pos = token.end;
// Check that the tag is terminated by a space or >>
if(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
return null;
}
// Process attributes
pos = $tw.utils.parseMacroParametersAsAttributes(node,source,pos);
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double closing angle bracket
token = $tw.utils.parseTokenString(source,pos,">>");
if(!token) {
return null;
}
node.end = token.end;
return node;
};
/*
Look for an MVV (multi-valued variable) reference as a transclusion, i.e. ((varname)) or ((varname params))
Returns null if not found, or a parse tree node of type "transclude" with isMVV: true
*/
exports.parseMVVReferenceAsTransclusion = function(source,pos) {
var node = {
type: "transclude",
isMVV: true,
start: pos,
attributes: {},
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=:)]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening parenthesis
var token = $tw.utils.parseTokenString(source,pos,"((");
if(!token) {
return null;
}
pos = token.end;
// Get the variable name
token = $tw.utils.parseTokenRegExp(source,pos,reVarName);
if(!token) {
return null;
}
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double closing parenthesis
token = $tw.utils.parseTokenString(source,pos,"))");
if(!token) {
return null;
}
node.end = token.end;
return node;
};
/*
Parse macro parameters as attributes. Returns the position after the last attribute
*/
exports.parseMacroParametersAsAttributes = function(node,source,pos) {
var position = 0,
attribute = $tw.utils.parseMacroParameterAsAttribute(source,pos);
while(attribute) {
if(!attribute.name) {
attribute.name = (position++) + "";
attribute.isPositional = true;
}
node.orderedAttributes.push(attribute);
node.attributes[attribute.name] = attribute;
pos = attribute.end;
// Get the next attribute
attribute = $tw.utils.parseMacroParameterAsAttribute(source,pos);
}
node.end = pos;
return pos;
};
/*
Parse a macro parameter as an attribute. Returns null if not found, otherwise returns {name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}, with the name being optional
*/
exports.parseMacroParameterAsAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
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 and the separator token
var nameToken = $tw.utils.parseTokenRegExp(source,pos,reAttributeName),
namePos = nameToken && $tw.utils.skipWhiteSpace(source,nameToken.end),
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/g),
isNewStyleSeparator = false; // If there is no separator then we don't allow new style values
// If we have a name and a separator then we have a named attribute
if(nameToken && separatorToken) {
node.name = nameToken.match[1];
// key value separator is `=` or `:`
node.assignmentOperator = separatorToken.match[0];
pos = separatorToken.end;
isNewStyleSeparator = (node.assignmentOperator === "=");
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
// Mark the value as having been quoted in the source
node.quoted = true;
} else {
// Look for a filtered value
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
if(filteredValue && isNewStyleSeparator) {
pos = filteredValue.end;
node.type = "filtered";
node.filter = filteredValue.match[1];
} else {
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue && isNewStyleSeparator) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation && isNewStyleSeparator) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference && isNewStyleSeparator) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
} else {
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue && isNewStyleSeparator) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
}
}
}
}
}
}
}
// Bail if we don't have a value
if(!node.type) {
return null;
}
// Update the end position
node.end = pos;
return node;
};
@@ -296,7 +477,7 @@ exports.parseFilterVariable = function(source) {
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}
Look for an HTML attribute definition. Returns null if not found, otherwise returns {name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
@@ -346,19 +527,20 @@ exports.parseAttribute = function(source,pos) {
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocation(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = macroInvocation;
node.value = mvvReference;
node.isMVV = true;
} else {
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
@@ -366,8 +548,16 @@ exports.parseAttribute = function(source,pos) {
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
} else {
node.type = "string";
node.value = "true";
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
node.type = "string";
node.value = "true";
}
}
}
}
@@ -375,6 +565,7 @@ exports.parseAttribute = function(source,pos) {
}
}
} else {
// If there is no equals sign or colon, then this is an attribute with no value, defaulting to "true"
node.type = "string";
node.value = "true";
}

View File

@@ -11,11 +11,10 @@ The PDF parser embeds a PDF viewer
var ImageParser = function(type,text,options) {
var element = {
type: "element",
tag: "iframe",
attributes: {}
},
src;
type: "element",
tag: "iframe",
attributes: {}
};
if(options._canonical_uri) {
element.attributes.src = {type: "string", value: options._canonical_uri};
} else if(text) {

View File

@@ -11,14 +11,13 @@ The video parser parses a video tiddler into an embeddable HTML element
var VideoParser = function(type,text,options) {
var element = {
type: "element",
tag: "video",
attributes: {
controls: {type: "string", value: "controls"},
style: {type: "string", value: "width: 100%; object-fit: contain"}
}
},
src;
type: "element",
tag: "video",
attributes: {
controls: {type: "string", value: "controls"},
style: {type: "string", value: "width: 100%; object-fit: contain"}
}
};
if(options._canonical_uri) {
element.attributes.src = {type: "string", value: options._canonical_uri};
} else if(text) {

View File

@@ -46,10 +46,10 @@ exports.parse = function() {
}
// Return the $codeblock widget
return [{
type: "codeblock",
attributes: {
code: {type: "string", value: text, start: codeStart, end: this.parser.pos},
language: {type: "string", value: this.match[1], start: languageStart, end: languageEnd}
}
type: "codeblock",
attributes: {
code: {type: "string", value: text, start: codeStart, end: this.parser.pos},
language: {type: "string", value: this.match[1], start: languageStart, end: languageEnd}
}
}];
};

View File

@@ -51,10 +51,10 @@ exports.parse = function() {
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
type: "void",
children: [],
text: this.parser.source.slice(commentStart, commentEnd),
start: commentStart,
end: commentEnd
}];
};

View File

@@ -44,9 +44,9 @@ exports.parse = function() {
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
type: "void",
text: this.parser.source.slice(commentStart, commentEnd),
start: commentStart,
end: commentEnd
}];
};

View File

@@ -95,7 +95,7 @@ exports.parseIfClause = function(filterCondition) {
hasLineBreak = !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g);
// If we found an else then we need to parse the body looking for the endif
var reEndString = "\\<\\%\\s*(endif)\\s*\\%\\>",
ex;
ex;
if(hasLineBreak) {
ex = this.parser.parseBlocksTerminatedExtended(reEndString);
} else {

View File

@@ -26,8 +26,6 @@ exports.init = function(parser) {
Parse the most recent match
*/
exports.parse = function() {
// Get all the details of the match
var entityString = this.match[1];
// Move past the macro call
this.parser.pos = this.matchRegExp.lastIndex;
// Return the entity

View File

@@ -32,7 +32,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*))?\)(\s*\r?\n)?/mg;
this.matchRegExp = /\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*(?:\)\)[^)]*)*))?\)(\s*\r?\n)?/mg;
};
/*

View File

@@ -29,7 +29,6 @@ exports.init = function(parser) {
Parse the most recent match
*/
exports.parse = function() {
var self = this;
// Move past the pragma invocation
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the filter terminated by a line break

View File

@@ -37,7 +37,7 @@ exports.parse = function() {
var paramString = this.match[2],
params = [];
if(paramString !== "") {
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))?/mg,
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[((?:[^\]]|\](?!\]))*)\]\]|([^"'\s]+)))?/mg,
paramMatch = reParam.exec(paramString);
while(paramMatch) {
// Save the parameter details

View File

@@ -0,0 +1,95 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/mvvdisplayinline.js
type: application/javascript
module-type: wikirule
Wiki rule for inline display of multi-valued variables and filter results.
Variable display: ((varname)) or ((varname||separator))
Filter display: (((filter))) or (((filter||separator)))
The default separator is ", " (comma space).
\*/
"use strict";
exports.name = "mvvdisplayinline";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
};
exports.findNextMatch = function(startPos) {
var source = this.parser.source;
var nextStart = startPos;
while((nextStart = source.indexOf("((",nextStart)) >= 0) {
if(source.charAt(nextStart + 2) === "(") {
// Filter mode: (((filter))) or (((filter||sep)))
var match = /^\(\(\(([\s\S]+?)\)\)\)/.exec(source.substring(nextStart));
if(match) {
// Check for separator: split on last || before )))
var inner = match[1];
var sepIndex = inner.lastIndexOf("||");
if(sepIndex >= 0) {
this.nextMatch = {
type: "filter",
filter: inner.substring(0,sepIndex),
separator: inner.substring(sepIndex + 2),
start: nextStart,
end: nextStart + match[0].length
};
} else {
this.nextMatch = {
type: "filter",
filter: inner,
separator: ", ",
start: nextStart,
end: nextStart + match[0].length
};
}
return nextStart;
}
} else {
// Variable mode: ((varname)) or ((varname||sep))
var match = /^\(\(([^()|]+?)(?:\|\|([^)]*))?\)\)/.exec(source.substring(nextStart));
if(match) {
this.nextMatch = {
type: "variable",
varName: match[1],
separator: match[2] !== undefined ? match[2] : ", ",
start: nextStart,
end: nextStart + match[0].length
};
return nextStart;
}
}
nextStart += 2;
}
return undefined;
};
/*
Parse the most recent match
*/
exports.parse = function() {
var match = this.nextMatch;
this.nextMatch = null;
this.parser.pos = match.end;
var filter, sep = match.separator;
if(match.type === "variable") {
filter = "[(" + match.varName + ")join[" + sep + "]]";
} else {
filter = match.filter + " +[join[" + sep + "]]";
}
return [{
type: "text",
attributes: {
text: {name: "text", type: "filtered", filter: filter}
},
orderedAttributes: [
{name: "text", type: "filtered", filter: filter}
]
}];
};

View File

@@ -93,7 +93,7 @@ exports.parseLink = function(source,pos) {
splitPos = null;
}
// Pull out the tooltip and URL
var tooltip, URL, urlStart;
var URL, urlStart;
textNode.start = pos;
if(splitPos) {
urlStart = splitPos + 1;

View File

@@ -67,5 +67,5 @@ exports.parse = function() {
return [{
type: "void",
children: tree
}]
}];
};

View File

@@ -60,7 +60,7 @@ var processRow = function(prevColumns) {
// End of row
if(prevCell && colSpanCount > 1) {
if(prevCell.attributes && prevCell.attributes && prevCell.attributes.colspan) {
colSpanCount += prevCell.attributes.colspan.value;
colSpanCount += prevCell.attributes.colspan.value;
} else {
colSpanCount -= 1;
}
@@ -163,7 +163,7 @@ exports.parse = function() {
table.children.splice(0,0,rowContainer); // Insert it at the bottom
}
// Set the alignment - TODO: figure out why TW did this
// rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
// rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
// Parse the caption
rowContainer.children = this.parser.parseInlineRun(rowTermRegExp,{eatTerminator: true});
} else {

View File

@@ -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;
@@ -53,17 +32,17 @@ exports.parse = function() {
params = this.match[3] ? this.match[3].split("|") : [];
// Prepare the transclude widget
var transcludeNode = {
type: "transclude",
attributes: {},
isBlock: true
};
type: "transclude",
attributes: {},
isBlock: true
};
$tw.utils.each(params,function(paramValue,index) {
var name = "" + index;
transcludeNode.attributes[name] = {
name: name,
type: "string",
value: paramValue
}
};
});
// Prepare the tiddler widget
var tr, targetTitle, targetField, targetIndex, tiddlerNode;

View File

@@ -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;
@@ -53,16 +32,16 @@ exports.parse = function() {
params = this.match[3] ? this.match[3].split("|") : [];
// Prepare the transclude widget
var transcludeNode = {
type: "transclude",
attributes: {}
};
type: "transclude",
attributes: {}
};
$tw.utils.each(params,function(paramValue,index) {
var name = "" + index;
transcludeNode.attributes[name] = {
name: name,
type: "string",
value: paramValue
}
};
});
// Prepare the tiddler widget
var tr, targetTitle, targetField, targetIndex, tiddlerNode;

View File

@@ -25,8 +25,6 @@ $$$
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.name = "typedblock";
exports.types = {block: true};

View File

@@ -49,8 +49,7 @@ PluginSwitcher.prototype.switchPlugins = function() {
var tiddler = self.wiki.getTiddler(title);
if(tiddler && tiddler.isPlugin() && plugins.indexOf(title) === -1) {
plugins.push(title);
var pluginInfo = $tw.utils.parseJSONSafe(self.wiki.getTiddlerText(title)),
dependents = $tw.utils.parseStringArray(tiddler.fields.dependents || "");
var dependents = $tw.utils.parseStringArray(tiddler.fields.dependents || "");
$tw.utils.each(dependents,function(title) {
accumulatePlugin(title);
});
@@ -58,11 +57,11 @@ PluginSwitcher.prototype.switchPlugins = function() {
};
accumulatePlugin(selectedPluginTitle);
// Read the plugin info for the incoming plugins
var changes = $tw.wiki.readPluginInfo(plugins);
$tw.wiki.readPluginInfo(plugins);
// Unregister any existing theme tiddlers
var unregisteredTiddlers = $tw.wiki.unregisterPluginTiddlers(this.pluginType);
$tw.wiki.unregisterPluginTiddlers(this.pluginType);
// Register any new theme tiddlers
var registeredTiddlers = $tw.wiki.registerPluginTiddlers(this.pluginType,plugins);
$tw.wiki.registerPluginTiddlers(this.pluginType,plugins);
// Unpack the current theme tiddlers
$tw.wiki.unpackPluginTiddlers();
// Call the switch handler

View File

@@ -32,10 +32,10 @@ function SaverHandler(options) {
this.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));
// Count of changes that have not yet been saved
var filteredChanges = self.filterFn.call(self.wiki,function(iterator) {
$tw.utils.each(self.preloadDirty,function(title) {
var tiddler = self.wiki.getTiddler(title);
iterator(tiddler,title);
});
$tw.utils.each(self.preloadDirty,function(title) {
var tiddler = self.wiki.getTiddler(title);
iterator(tiddler,title);
});
});
this.numChanges = filteredChanges.length;
// Listen out for changes to tiddlers

View File

@@ -15,27 +15,27 @@ var AndTidWiki = function(wiki) {
AndTidWiki.prototype.save = function(text,method,callback,options) {
var filename = options && options.variables ? options.variables.filename : null;
if (method === "download") {
if(method === "download") {
// Support download
if (window.twi.saveDownload) {
if(window.twi.saveDownload) {
try {
window.twi.saveDownload(text,filename);
} catch(err) {
if (err.message === "Method not found") {
if(err.message === "Method not found") {
window.twi.saveDownload(text);
}
}
} else {
var link = document.createElement("a");
link.setAttribute("href","data:text/plain," + encodeURIComponent(text));
if (filename) {
link.setAttribute("download",filename);
if(filename) {
link.setAttribute("download",filename);
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
} else if (window.twi.saveWiki) {
} else if(window.twi.saveWiki) {
// Direct save in Tiddloid
window.twi.saveWiki(text);
} else {

View File

@@ -22,7 +22,7 @@ var findSaver = function(window) {
console.log({ msg: "custom saver is disabled", reason: err });
return null;
}
}
};
var saver = findSaver(window) || findSaver(window.parent) || {};
var CustomSaver = function(wiki) {

View File

@@ -80,7 +80,7 @@ GiteaSaver.prototype.save = function(text,method,callback) {
callback: function(err,getResponseDataJson,xhr) {
if(xhr.status === 404) {
callback("Please ensure the branch in the Gitea repo exists");
}else{
} else {
data["branch"] = branch;
self.upload(uri + filename, use_put?"PUT":"POST", headers, data, callback);
}
@@ -101,7 +101,6 @@ GiteaSaver.prototype.upload = function(uri,method,headers,data,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
callback(null);
}
});

View File

@@ -17,8 +17,7 @@ var GitHubSaver = function(wiki) {
};
GitHubSaver.prototype.save = function(text,method,callback) {
var self = this,
username = this.wiki.getTiddlerText("$:/GitHub/Username"),
var username = this.wiki.getTiddlerText("$:/GitHub/Username"),
password = $tw.utils.getPassword("github"),
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
path = this.wiki.getTiddlerText("$:/GitHub/Path",""),
@@ -81,7 +80,6 @@ GitHubSaver.prototype.save = function(text,method,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
callback(null);
}
});

View File

@@ -18,8 +18,7 @@ var GitLabSaver = function(wiki) {
GitLabSaver.prototype.save = function(text,method,callback) {
/* See https://docs.gitlab.com/ee/api/repository_files.html */
var self = this,
username = this.wiki.getTiddlerText("$:/GitLab/Username"),
var username = this.wiki.getTiddlerText("$:/GitLab/Username"),
password = $tw.utils.getPassword("gitlab"),
repo = this.wiki.getTiddlerText("$:/GitLab/Repo"),
path = this.wiki.getTiddlerText("$:/GitLab/Path",""),
@@ -45,7 +44,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
var uri = endpoint + "/projects/" + encodeURIComponent(repo) + "/repository/";
// Perform a get request to get the details (inc shas) of files in the same path as our file
$tw.utils.httpRequest({
url: uri + "tree/?path=" + encodeURIComponent(path.replace(/^\/+|\/$/g, '')) + "&branch=" + encodeURIComponent(branch.replace(/^\/+|\/$/g, '')),
url: uri + "tree/?path=" + encodeURIComponent(path.replace(/^\/+|\/$/g, "")) + "&branch=" + encodeURIComponent(branch.replace(/^\/+|\/$/g, "")),
type: "GET",
headers: headers,
callback: function(err,getResponseDataJson,xhr) {
@@ -71,7 +70,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
};
// Perform a request to save the file
$tw.utils.httpRequest({
url: uri + "files/" + encodeURIComponent(path.replace(/^\/+/, '') + filename),
url: uri + "files/" + encodeURIComponent(path.replace(/^\/+/, "") + filename),
type: requestType,
headers: headers,
data: JSON.stringify(data),
@@ -79,7 +78,6 @@ GitLabSaver.prototype.save = function(text,method,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
callback(null);
}
});

View File

@@ -6,10 +6,7 @@ module-type: saver
Handles saving changes via window.postMessage() to the window.parent
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
@@ -63,4 +60,3 @@ exports.create = function(wiki) {
return new PostMessageSaver(wiki);
};
})();

View File

@@ -94,7 +94,7 @@ PutSaver.prototype.save = function(text,method,callback) {
} else if(status === 403) { // permission denied
errorMsg = $tw.language.getString("Error/PutForbidden");
}
if (xhr.responseText) {
if(xhr.responseText) {
// treat any server response like a plain text error explanation
errorMsg = errorMsg + "\n\n" + xhr.responseText;
}

View File

@@ -28,7 +28,7 @@ UploadSaver.prototype.save = function(text,method,callback) {
uploadWithUrlOnly = this.wiki.getTextReference("$:/UploadWithUrlOnly") || "no",
url = this.wiki.getTextReference("$:/UploadURL");
// Bail out if we don't have the bits we need
if (uploadWithUrlOnly === "yes") {
if(uploadWithUrlOnly === "yes") {
// The url is good enough. No need for a username and password.
// Assume the server uses some other kind of auth mechanism.
if(!url || url.toString().trim() === "") {
@@ -48,7 +48,6 @@ UploadSaver.prototype.save = function(text,method,callback) {
}
// Assemble the header
var boundary = "---------------------------" + "AaB03x";
var uploadFormName = "UploadPlugin";
var head = [];
head.push("--" + boundary + "\r\nContent-disposition: form-data; name=\"UploadPlugin\"\r\n");
head.push("backupDir=" + backupDir + ";user=" + username + ";password=" + password + ";uploaddir=" + uploadDir + ";;");

View File

@@ -59,7 +59,7 @@ function loadIFrame(url,callback) {
Unload library iframe for given url
*/
function unloadIFrame(url){
var iframes = document.getElementsByTagName('iframe');
var iframes = document.getElementsByTagName("iframe");
for(var t=iframes.length-1; t--; t>=0) {
var iframe = iframes[t];
if(iframe.getAttribute("library") === "true" &&

Some files were not shown because too many files have changed in this diff Show More