diff --git a/.eslintrc.yml b/.eslintrc.yml
index 049af59e4..0316b8385 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -231,7 +231,10 @@ rules:
prefer-spread: 'off'
prefer-template: 'off'
quote-props: 'off'
- quotes: 'off'
+ quotes:
+ - error
+ - double
+ - avoidEscape: true
radix: 'off'
require-atomic-updates: error
require-await: error
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 1e644e161..286a842bc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -21,7 +21,7 @@ body:
attributes:
label: To Reproduce
description: "Steps to reproduce the behavior:"
- value: |
+ placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@@ -41,7 +41,7 @@ body:
attributes:
label: TiddlyWiki Configuration
description: please complete the following information
- value: |
+ placeholder: |
- Version [e.g. v5.1.24]
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
- Plugins installed [e.g. Freelinks, TiddlyMap]
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 556b93919..dca23b783 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,7 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: Discuss feature request
- url: https://github.com/Jermolene/TiddlyWiki5/discussions
+ url: https://github.com/TiddlyWiki/TiddlyWiki5/discussions
about: Open new discussion about new feature
- name: Talk.Tiddlywiki Forum
url: https://talk.tiddlywiki.org
diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml
new file mode 100644
index 000000000..72bba1c54
--- /dev/null
+++ b/.github/workflows/cla-check.yml
@@ -0,0 +1,30 @@
+name: Check CLA Signature
+on:
+ pull_request_target:
+ types:
+ - opened
+ - reopened
+ paths-ignore:
+ - 'licenses/cla-individual.md'
+jobs:
+ check_cla:
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ if: ${{ (github.event.pull_request.user.login != github.repository_owner) }}
+ steps:
+ - run: |
+ if ! curl -s https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/tiddlywiki-com/licenses/cla-individual.md | grep -o "@$USER,"; then
+ echo "CLA not signed"
+ gh pr comment "$NUMBER" -b "@$USER It appears that this is your first contribution to the project, welcome.
+
+ With apologies for the bureaucracy, please could you prepare a separate PR to the 'tiddlywiki-com' branch with your signature for the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))."
+ else
+ echo "CLA already signed"
+ gh pr comment "$NUMBER" -b "Confirmed: **$USER** has already signed the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))"
+ fi
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_REPO: ${{ github.repository }}
+ NUMBER: ${{ github.event.pull_request.number }}
+ USER: ${{ github.actor }}
diff --git a/.github/workflows/cla-signed.yml b/.github/workflows/cla-signed.yml
new file mode 100644
index 000000000..6783219d1
--- /dev/null
+++ b/.github/workflows/cla-signed.yml
@@ -0,0 +1,70 @@
+name: CLA Signed
+
+on:
+ pull_request_target:
+ types:
+ - opened
+ - closed
+ paths:
+ - 'licenses/cla-individual.md'
+
+env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_REPO: ${{ github.repository }}
+ NUMBER: ${{ github.event.pull_request.number }}
+ AUTHOR: ${{ github.event.pull_request.user.login }}
+
+jobs:
+ # check if PRs updating the CLA are targetting the tiddlywiki-com branch
+ check-signature-branch:
+ if: (github.event.pull_request.merged != true) && (github.event.pull_request.user.login != github.repository_owner)
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - run: |
+ if ! $BRANCH == "tiddlywiki-com"; then
+ echo "This CLA signature targets the wrong branch"
+ gh pr comment "$NUMBER" -b "@$AUTHOR Signatures to the CLA must target the 'tiddlywiki-com' branch."
+ fi
+ env:
+ BRANCH: ${{ github.event.pull_request.base.ref }}
+
+ # leave a comment on each open PR by a given author when their signature is added to the CLA
+ cla-signed:
+ if: (github.event.pull_request.merged == true) && (github.event.pull_request.user.login != github.repository_owner)
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - name: List open PRs by user
+ id: list-prs
+ uses: actions/github-script@v6
+ with:
+ result-encoding: string
+ script: |
+ const owner = context.repo.owner,
+ repo = context.repo.repo,
+ author = context.payload.pull_request.user.login;
+
+ const { data: pullRequests } = await github.rest.pulls.list({
+ owner: owner,
+ repo: repo,
+ state: 'open',
+ sort: 'created',
+ direction: 'desc',
+ per_page: 100
+ });
+ const userPullRequests = pullRequests.filter(pr => pr.user.login === author),
+ prNumbers = userPullRequests.map(pr => pr.number).join(',');
+ console.log(`Open pull requests by ${author}:${prNumbers}`);
+ return prNumbers;
+
+ - name: Comment open PRs by the same author
+ run: |
+ prs=($(echo ${{ steps.list-prs.outputs.result }} | tr "," "\n"))
+
+ for number in "${prs[@]}"
+ do
+ gh pr comment "$number" -b "**$AUTHOR** has signed the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))"
+ done
diff --git a/.gitignore b/.gitignore
index 0ab5b300f..412759161 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ node_modules/
/test-results/
/playwright-report/
/playwright/.cache/
+$__StoryList.tid
diff --git a/bin/build-site.sh b/bin/build-site.sh
index a2193953d..fbb34cc98 100755
--- a/bin/build-site.sh
+++ b/bin/build-site.sh
@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
- TW5_BUILD_VERSION=v5.3.3
+ TW5_BUILD_VERSION=v5.3.6
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -393,6 +393,17 @@ node $TW5_BUILD_TIDDLYWIKI \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/highlight/empty.html text/plain \
|| exit 1
+# /plugins/tiddlywiki/geospatial/index.html Demo wiki with geospatial plugin
+# /plugins/tiddlywiki/geospatial/empty.html Empty wiki with geospatial plugin
+node $TW5_BUILD_TIDDLYWIKI \
+ ./editions/geospatialdemo \
+ --verbose \
+ --load $TW5_BUILD_OUTPUT/build.tid \
+ --output $TW5_BUILD_OUTPUT \
+ --rendertiddler $:/core/save/all plugins/tiddlywiki/geospatial/index.html text/plain \
+ --rendertiddler $:/core/save/empty plugins/tiddlywiki/geospatial/empty.html text/plain \
+ || exit 1
+
######################################################
#
# Language editions
diff --git a/bin/ci-pre-build.sh b/bin/ci-pre-build.sh
index 6f4b0ca78..a11b8e0c4 100755
--- a/bin/ci-pre-build.sh
+++ b/bin/ci-pre-build.sh
@@ -7,4 +7,4 @@ npm --force install tiddlywiki || exit 1
# Pull existing GitHub pages content
-git clone --depth=1 --branch=master "https://github.com/Jermolene/jermolene.github.io.git" output
+git clone --depth=1 --branch=master "https://github.com/TiddlyWiki/tiddlywiki.com-gh-pages.git" output
diff --git a/bin/ci-push.sh b/bin/ci-push.sh
index dff297c80..fe8373785 100755
--- a/bin/ci-push.sh
+++ b/bin/ci-push.sh
@@ -10,6 +10,6 @@ git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
git add -A .
git commit --message "GitHub build: $GITHUB_RUN_NUMBER of $TW5_BUILD_BRANCH ($(date +'%F %T %Z'))"
-git remote add deploy "https://$GH_TOKEN@github.com/Jermolene/jermolene.github.io.git" &>/dev/null
+git remote add deploy "https://$GH_TOKEN@github.com/TiddlyWiki/tiddlywiki.com-gh-pages.git" &>/dev/null
git push deploy master &>/dev/null
cd ..
diff --git a/bin/readme-bld.sh b/bin/readme-bld.sh
index 198c3abd0..e7c9df564 100755
--- a/bin/readme-bld.sh
+++ b/bin/readme-bld.sh
@@ -15,3 +15,11 @@ node $TW5_BUILD_TIDDLYWIKI \
--output . \
--build readmes \
|| exit 1
+
+# tw.org readmes
+node $TW5_BUILD_TIDDLYWIKI \
+ editions/tw.org \
+ --verbose \
+ --output . \
+ --build readmes \
+ || exit 1
diff --git a/boot/boot.js b/boot/boot.js
index 64cedab77..b4bdc00f2 100644
--- a/boot/boot.js
+++ b/boot/boot.js
@@ -142,15 +142,15 @@ $tw.utils.each = function(object,callback) {
var next,f,length;
if(object) {
if(Object.prototype.toString.call(object) == "[object Array]") {
- for (f=0, length=object.length; fThis community exists because TiddlyWiki is more useful when people share and work together.
This community is a beautiful but fragile thing: a collection of diverse people from all over the planet, united in their interest in the project, and their commitment to helping one another achieve and learn more.
We try to make the community as broad and welcoming as possible by remembering some basic principles of culture and behaviour.
These principles guide technical and non-technical decisions, and help contributors and leaders support our project and community.
We are optimistic and hopeful
We aim to foster a learning environment that is collaborative and safe for everyone
We recognise that the motivation for sharing and helping is usually for appreciation, and not financial gain, and so we take care to acknowledge and thank the people who enrich the community by sharing what they have created
While we are united in our interest in TiddlyWiki, we differ in every other conceivable way. We choose to focus on what unites us, and avoid unnecessarily mixing contentious topics like religion and politics
We treat each other with respect, and start with the assumption that others are acting in good faith
We avoid discriminatory language
We try to use our strength as a community to help others
We avoid responding when angry or upset because we try to de-escalate conflict
We make sure we critique ideas, not people
When we disagree with others we do so graciously, and treat others with dignity and respoect
We do not tolerate intolerance towards others
We seek first to understand others, and then to be understood
We have fun
Our discussions are in English. It is not the first language of many people in the community, nor do we all share the same cultural background and reference points. So we take care to use language that is clear and unambigous, and avoid cultural references or jokes that will not be widely understood.
It is not acceptable to make jokes or other comments that discriminate by race, gender, sexuality, or other protected characteristic.
As an inclusive community, we are committed to making sure that TiddlyWiki is an accessible tool that understands the needs of people with disabilities.
\ No newline at end of file
diff --git a/contributing.md b/contributing.md
index 9dc10d0da..707c34110 100644
--- a/contributing.md
+++ b/contributing.md
@@ -1,3 +1,3 @@
-
PRs must meet these minimum requirements before they can be considered for merging:
The material in the PR must be free of licensing restrictions. Which means that either:
The author must hold the copyright in all of the material themselves
The material must be licensed under a license compatible with TiddlyWiki's BSD license
The author must sign the Contributors License Agreement (see below)
Each PR should only make a single feature change
The title of the PR should be 50 characters or less
The title of the PR should be capitalised, and should not end with a period
The title of the PR should be written in the imperative mood. See below
Adequate explanation in the body of the PR for the motivation and implementation of the change. Focus on the why and what, rather than the how
PRs must be self-contained. Although they can link to material elsewhere, everything needed to understand the intention of the PR should be included
Any visual changes introduced by the PR should be noted and illustrated with before/after screenshots
Documentation as appropriate for end-users or developers
Observe the coding style
Read the developers documentation
Please open a consultation issue prior to investing time in making a large PR
Imperative Mood for PR Titles
The "imperative mood" means written as if giving a command or instruction. See this post for more details, but the gist is that the title of the PR should make sense when used to complete the sentence "If applied, this commit will...". So for example, these are good PR titles:
If applied, this commit will update the contributing guidelines
If applied, this commit will change css-escape-polyfill to a $tw.utils method
If applied, this commit will make it easier to subclass the wikitext parser with a custom rule set
These a poorly worded PR titles:
If applied, this commit will edit text widgets should use default text for missing fields
If applied, this commit will signing the CLA
If applied, this commit will don't crash if options.event is missing
PR titles may also include a short prefix to indicate the subsystem to which they apply. For example:
Menu plugin: Include menu text in aerial rotator
Commenting on Pull Requests
One of the principles of open source is that many pairs of eyes on the code can improve quality. So, we welcome comments and critiques of pending PRs. Conventional Comments has some techniques to help make comments as constructive and actionable as possible. Notably, they recommend prefixing a comment with a label to clarify the intention:
praise
Praises highlight something positive. Try to leave at least one of these comments per review. Do not leave false praise (which can actually be damaging). Do look for something to sincerely praise
nitpick
Nitpicks are small, trivial, but necessary changes. Distinguishing nitpick comments significantly helps direct the reader's attention to comments requiring more involvement
suggestion
Suggestions are specific requests to improve the subject under review. It is assumed that we all want to do what's best, so these comments are never dismissed as “mere suggestions”, but are taken seriously
issue
Issues represent user-facing problems. If possible, it's great to follow this kind of comment with a suggestion
question
Questions are appropriate if you have a potential concern but are not quite sure if it's relevant or not. Asking the author for clarification or investigation can lead to a quick resolution
thought
Thoughts represent an idea that popped up from reviewing. These comments are non-blocking by nature, but they are extremely valuable and can lead to more focused initiatives and mentoring opportunities
chore
Chores are simple tasks that must be done before the subject can be “officially” accepted. Usually, these comments reference some common process. Try to leave a link to the process description so that the reader knows how to resolve the chore
Contributor License Agreement
Like other OpenSource projects, TiddlyWiki5 needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the UnaMesa Association (the legal entity that owns TiddlyWiki on behalf of the community).
Ensure that the "branch" dropdown at the top left is set to tiddlywiki-com
Click the "edit" button at the top-right corner (clicking this button will fork the project so you can edit the file)
Add your name at the bottom
eg: Jeremy Ruston, @Jermolene, 2011/11/22
Below the edit box for the CLA text you should see a box labelled Propose file change
Enter a brief title to explain the change (eg, "Signing the CLA")
Click the green button labelled Propose file change
On the following screen, click the green button labelled Create pull request
The CLA documents used for this project were created using Harmony Project Templates. "HA-CLA-I-LIST Version 1.0" for "CLA-individual" and "HA-CLA-E-LIST Version 1.0" for "CLA-entity".
+
PRs must meet these minimum requirements before they can be considered for merging:
The material in the PR must be free of licensing restrictions. Which means that either:
The author must hold the copyright in all of the material themselves
The material must be licensed under a license compatible with TiddlyWiki's BSD license
The author must sign the Contributors License Agreement (see below)
Each PR should only make a single feature change
The title of the PR should be 50 characters or less
The title of the PR should be capitalised, and should not end with a period
The title of the PR should be written in the imperative mood. See below
Adequate explanation in the body of the PR for the motivation and implementation of the change. Focus on the why and what, rather than the how
PRs must be self-contained. Although they can link to material elsewhere, everything needed to understand the intention of the PR should be included
Any visual changes introduced by the PR should be noted and illustrated with before/after screenshots
Documentation as appropriate for end-users or developers
Observe the coding style
Read the developers documentation
Please open a consultation issue prior to investing time in making a large PR
Imperative Mood for PR Titles
The "imperative mood" means written as if giving a command or instruction. See this post for more details, but the gist is that the title of the PR should make sense when used to complete the sentence "If applied, this commit will...". So for example, these are good PR titles:
If applied, this commit will update the contributing guidelines
If applied, this commit will change css-escape-polyfill to a $tw.utils method
If applied, this commit will make it easier to subclass the wikitext parser with a custom rule set
These a poorly worded PR titles:
If applied, this commit will edit text widgets should use default text for missing fields
If applied, this commit will signing the CLA
If applied, this commit will don't crash if options.event is missing
PR titles may also include a short prefix to indicate the subsystem to which they apply. For example:
Menu plugin: Include menu text in aerial rotator
Commenting on Pull Requests
One of the principles of open source is that many pairs of eyes on the code can improve quality. So, we welcome comments and critiques of pending PRs. Conventional Comments has some techniques to help make comments as constructive and actionable as possible. Notably, they recommend prefixing a comment with a label to clarify the intention:
praise
Praises highlight something positive. Try to leave at least one of these comments per review. Do not leave false praise (which can actually be damaging). Do look for something to sincerely praise
nitpick
Nitpicks are small, trivial, but necessary changes. Distinguishing nitpick comments significantly helps direct the reader's attention to comments requiring more involvement
suggestion
Suggestions are specific requests to improve the subject under review. It is assumed that we all want to do what's best, so these comments are never dismissed as “mere suggestions”, but are taken seriously
issue
Issues represent user-facing problems. If possible, it's great to follow this kind of comment with a suggestion
question
Questions are appropriate if you have a potential concern but are not quite sure if it's relevant or not. Asking the author for clarification or investigation can lead to a quick resolution
thought
Thoughts represent an idea that popped up from reviewing. These comments are non-blocking by nature, but they are extremely valuable and can lead to more focused initiatives and mentoring opportunities
chore
Chores are simple tasks that must be done before the subject can be “officially” accepted. Usually, these comments reference some common process. Try to leave a link to the process description so that the reader knows how to resolve the chore
Contributor License Agreement
Like other OpenSource projects, TiddlyWiki5 needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the UnaMesa Association (the legal entity that owns TiddlyWiki on behalf of the community).
Ensure that the "branch" dropdown at the top left is set to tiddlywiki-com
Click the "edit" button at the top-right corner (clicking this button will fork the project so you can edit the file)
Add your name at the bottom
eg: Jeremy Ruston, @Jermolene, 2011/11/22
Below the edit box for the CLA text you should see a box labelled Propose file change
Enter a brief title to explain the change (eg, "Signing the CLA")
Click the green button labelled Propose file change
On the following screen, click the green button labelled Create pull request
The CLA documents used for this project were created using Harmony Project Templates. "HA-CLA-I-LIST Version 1.0" for "CLA-individual" and "HA-CLA-E-LIST Version 1.0" for "CLA-entity".
This file was automatically generated by TiddlyWiki5
\ No newline at end of file
diff --git a/core/images/discord.tid b/core/images/discord.tid
new file mode 100644
index 000000000..7510babb4
--- /dev/null
+++ b/core/images/discord.tid
@@ -0,0 +1,5 @@
+title: $:/core/images/discord
+tags: $:/tags/Image
+
+\parameters (size:"22pt")
+
\ No newline at end of file
diff --git a/core/images/input-button.tid b/core/images/input-button.tid
new file mode 100644
index 000000000..731a1e0cd
--- /dev/null
+++ b/core/images/input-button.tid
@@ -0,0 +1,5 @@
+title: $:/core/images/input-button
+tags: $:/tags/Image
+
+\parameters (size:"22pt")
+
\ No newline at end of file
diff --git a/core/images/standard-layout.tid b/core/images/standard-layout.tid
new file mode 100644
index 000000000..1b83375c9
--- /dev/null
+++ b/core/images/standard-layout.tid
@@ -0,0 +1,7 @@
+title: $:/core/images/standard-layout
+tags: $:/tags/Image
+
+\parameters (size:"22pt")
+
\ No newline at end of file
diff --git a/core/language/en-GB/Buttons.multids b/core/language/en-GB/Buttons.multids
index fa769d117..30f89eec7 100644
--- a/core/language/en-GB/Buttons.multids
+++ b/core/language/en-GB/Buttons.multids
@@ -28,6 +28,7 @@ Encryption/ClearPassword/Caption: clear password
Encryption/ClearPassword/Hint: Clear the password and save this wiki without encryption
Encryption/SetPassword/Caption: set password
Encryption/SetPassword/Hint: Set a password for saving this wiki with encryption
+EmergencyDownload/Caption: download tiddlers as json
ExportPage/Caption: export all
ExportPage/Hint: Export all tiddlers
ExportTiddler/Caption: export tiddler
@@ -79,6 +80,7 @@ NewMarkdown/Caption: new Markdown tiddler
NewMarkdown/Hint: Create a new Markdown tiddler
NewTiddler/Caption: new tiddler
NewTiddler/Hint: Create a new tiddler
+OpenControlPanel/Hint: Open control panel
OpenWindow/Caption: open in new window
OpenWindow/Hint: Open tiddler in new window
Palette/Caption: palette
@@ -103,6 +105,8 @@ ShowSideBar/Caption: show sidebar
ShowSideBar/Hint: Show sidebar
TagManager/Caption: tag manager
TagManager/Hint: Open tag manager
+TestCaseImport/Caption: import tiddlers
+TestCaseImport/Hint: Import tiddlers
Timestamp/Caption: timestamps
Timestamp/Hint: Choose whether modifications update timestamps
Timestamp/On/Caption: timestamps are on
diff --git a/core/language/en-GB/ControlPanel.multids b/core/language/en-GB/ControlPanel.multids
index d8321edbf..a1b164c5c 100644
--- a/core/language/en-GB/ControlPanel.multids
+++ b/core/language/en-GB/ControlPanel.multids
@@ -198,6 +198,12 @@ Settings/TitleLinks/Yes/Description: Display tiddler titles as links
Settings/MissingLinks/Caption: Wiki Links
Settings/MissingLinks/Hint: Choose whether to link to tiddlers that do not exist yet
Settings/MissingLinks/Description: Enable links to missing tiddlers
+SocialCard/Caption: Social Media Card
+SocialCard/Domain/Prompt: Domain name to display for the link (for example, ''tiddlywiki.com'')
+SocialCard/Hint: This information is used by social and messaging services to display a preview card for links to this TiddlyWiki when hosted online
+SocialCard/PreviewUrl/Prompt: Full URL to preview image for this TiddlyWiki
+SocialCard/PreviewUrl/Preview: Preview image:
+SocialCard/Url/Prompt: Full URL of this TiddlyWiki
StoryTiddler/Caption: Story Tiddler
StoryTiddler/Hint: This rule cascade is used to dynamically choose the template for displaying a tiddler in the story river.
StoryView/Caption: Story View
@@ -206,6 +212,12 @@ Stylesheets/Caption: Stylesheets
Stylesheets/Expand/Caption: Expand All
Stylesheets/Hint: This is the rendered CSS of the current stylesheet tiddlers tagged with <>
Stylesheets/Restore/Caption: Restore
+TestCases/Caption: Test Cases
+TestCases/Hint: Test cases are self contained examples for testing and learning
+TestCases/All/Caption: All Test Cases
+TestCases/All/Hint: All Test Cases
+TestCases/Failed/Caption: Failed Test Cases
+TestCases/Failed/Hint: Only Failed Test Cases
Theme/Caption: Theme
Theme/Prompt: Current theme:
TiddlerFields/Caption: Tiddler Fields
@@ -229,3 +241,7 @@ ViewTemplateBody/Caption: View Template Body
ViewTemplateBody/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the body of a tiddler.
ViewTemplateTitle/Caption: View Template Title
ViewTemplateTitle/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the title of a tiddler.
+ViewTemplateSubtitle/Caption: View Template Subtitle
+ViewTemplateSubtitle/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the subtitle of a tiddler.
+ViewTemplateTags/Caption: View Template Tags
+ViewTemplateTags/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the tags area of a tiddler.
diff --git a/core/language/en-GB/Docs/PaletteColours.multids b/core/language/en-GB/Docs/PaletteColours.multids
index 98addbf85..bc1b36c3d 100644
--- a/core/language/en-GB/Docs/PaletteColours.multids
+++ b/core/language/en-GB/Docs/PaletteColours.multids
@@ -65,6 +65,13 @@ sidebar-tab-foreground-selected: Sidebar tab foreground for selected tabs
sidebar-tab-foreground: Sidebar tab foreground
sidebar-tiddler-link-foreground-hover: Sidebar tiddler link foreground hover
sidebar-tiddler-link-foreground: Sidebar tiddler link foreground
+stability-stable: Badge for stability level "stable"
+stability-experimental: Badge for stability level "experimental"
+stability-deprecated: Badge for stability level "deprecated"
+stability-legacy: Badge for stability level "legacy"
+testcase-accent-level-1: Test case accent colour with no nesting
+testcase-accent-level-2: Test case accent colour with 2nd level nesting
+testcase-accent-level-3: Test case accent colour with 3rd level nesting or higher
site-title-foreground: Site title foreground
static-alert-foreground: Static alert foreground
tab-background-selected: Tab background for selected tabs
diff --git a/core/language/en-GB/Fields.multids b/core/language/en-GB/Fields.multids
index 68804f082..9830e96c1 100644
--- a/core/language/en-GB/Fields.multids
+++ b/core/language/en-GB/Fields.multids
@@ -30,6 +30,7 @@ name: The human readable name associated with a plugin tiddler
parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin
plugin-priority: A numerical value indicating the priority of a plugin tiddler
plugin-type: The type of plugin in a plugin tiddler
+stability: The development status of a plugin: deprecated, experimental, stable, or legacy
revision: The revision of the tiddler held at the server
released: Date of a TiddlyWiki release
source: The source URL associated with a tiddler
diff --git a/core/language/en-GB/Misc.multids b/core/language/en-GB/Misc.multids
index b5e6e2374..d8c091375 100644
--- a/core/language/en-GB/Misc.multids
+++ b/core/language/en-GB/Misc.multids
@@ -70,7 +70,7 @@ No: No
OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library
OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
PageTemplate/Description: the default ~TiddlyWiki layout
-PageTemplate/Name: Default ~PageTemplate
+PageTemplate/Name: Standard Layout
PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect
RecentChanges/DateFormat: DDth MMM YYYY
Shortcuts/Input/AdvancedSearch/Hint: Open the ~AdvancedSearch panel from within the sidebar search field
diff --git a/core/language/en-GB/Snippets/FunctionDefinition.tid b/core/language/en-GB/Snippets/FunctionDefinition.tid
new file mode 100644
index 000000000..e000e38b1
--- /dev/null
+++ b/core/language/en-GB/Snippets/FunctionDefinition.tid
@@ -0,0 +1,7 @@
+title: $:/language/Snippets/FunctionDefinition
+tags: $:/tags/TextEditor/Snippet
+caption: Function definition
+
+\function f.name(param1,param2:"default value") [!is[blank]else]
+
+<>
diff --git a/core/language/en-GB/Snippets/ProcedureDefinition.tid b/core/language/en-GB/Snippets/ProcedureDefinition.tid
new file mode 100644
index 000000000..632abcc01
--- /dev/null
+++ b/core/language/en-GB/Snippets/ProcedureDefinition.tid
@@ -0,0 +1,7 @@
+title: $:/language/Snippets/ProcedureDefinition
+tags: $:/tags/TextEditor/Snippet
+caption: Procedure definition
+
+\procedure procName(param1:"default value",param2)
+Your text comes here.
+\end
diff --git a/core/language/en-GB/Types/image_x-icon.tid b/core/language/en-GB/Types/image_x-icon.tid
deleted file mode 100644
index 55420387a..000000000
--- a/core/language/en-GB/Types/image_x-icon.tid
+++ /dev/null
@@ -1,5 +0,0 @@
-title: $:/language/Docs/Types/image/x-icon
-description: ICO icon
-name: image/x-icon
-group: Image
-group-sort: 1
diff --git a/core/language/en-GB/Types/text_vnd.tiddlywiki_multiple.tid b/core/language/en-GB/Types/text_vnd.tiddlywiki_multiple.tid
new file mode 100644
index 000000000..af15d7ac3
--- /dev/null
+++ b/core/language/en-GB/Types/text_vnd.tiddlywiki_multiple.tid
@@ -0,0 +1,5 @@
+title: $:/language/Docs/Types/text/vnd.tiddlywiki-multiple
+description: Compound tiddler
+name: text/vnd.tiddlywiki-multiple
+group: Developer
+group-sort: 2
diff --git a/core/modules/commands/listen.js b/core/modules/commands/listen.js
index 3c5f6a63a..ca6e6e076 100644
--- a/core/modules/commands/listen.js
+++ b/core/modules/commands/listen.js
@@ -18,7 +18,7 @@ exports.info = {
name: "listen",
synchronous: true,
namedParameterMode: true,
- mandatoryParameters: [],
+ mandatoryParameters: []
};
var Command = function(params,commander,callback) {
diff --git a/core/modules/commands/makelibrary.js b/core/modules/commands/makelibrary.js
index 36a1399a2..3af2e4943 100644
--- a/core/modules/commands/makelibrary.js
+++ b/core/modules/commands/makelibrary.js
@@ -27,33 +27,8 @@ var Command = function(params,commander,callback) {
Command.prototype.execute = function() {
var wiki = this.commander.wiki,
- fs = require("fs"),
- path = require("path"),
upgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,
- tiddlers = {};
- // Collect up the library plugins
- var collectPlugins = function(folder) {
- var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
- for(var p=0; p 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 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");
});
return null;
};
diff --git a/core/modules/commands/save.js b/core/modules/commands/save.js
index 9769cec69..3cb7ef08c 100644
--- a/core/modules/commands/save.js
+++ b/core/modules/commands/save.js
@@ -43,7 +43,9 @@ Saves individual tiddlers in their raw text or binary format to the specified fi
directory: path.resolve(self.commander.outputPath),
pathFilters: [filenameFilter],
wiki: wiki,
- fileInfo: {}
+ fileInfo: {
+ overwrite: true
+ }
});
if(self.commander.verbose) {
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
diff --git a/core/modules/commands/savewikifolder.js b/core/modules/commands/savewikifolder.js
index c0fccd775..461ff6f04 100644
--- a/core/modules/commands/savewikifolder.js
+++ b/core/modules/commands/savewikifolder.js
@@ -176,7 +176,10 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
var pluginTiddlers = $tw.utils.parseJSONSafe(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
- $tw.utils.each(pluginTiddlers,function(tiddler) {
+ $tw.utils.each(pluginTiddlers,function(tiddler,title) {
+ if(!tiddler.title) {
+ tiddler.title = title;
+ }
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
});
};
diff --git a/core/modules/config.js b/core/modules/config.js
index 399af598b..fdcf94d0f 100644
--- a/core/modules/config.js
+++ b/core/modules/config.js
@@ -30,7 +30,7 @@ exports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + "+" +
exports.textPrimitives.upperLetter +
exports.textPrimitives.anyLetter + "*";
-exports.htmlEntities = {quot:34, dollar:36, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
+exports.htmlEntities = {quot:34, dollar:36, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, nobreak:8288, NoBreak:8288, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
exports.htmlVoidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",");
diff --git a/core/modules/filters/backtranscludes.js b/core/modules/filters/backtranscludes.js
index 7d4215073..253b9dd7b 100644
--- a/core/modules/filters/backtranscludes.js
+++ b/core/modules/filters/backtranscludes.js
@@ -16,11 +16,11 @@ Filter operator for returning all the backtranscludes from a tiddler
Export our filter function
*/
exports.backtranscludes = function(source,operator,options) {
- var results = [];
+ var results = new $tw.utils.LinkedList();
source(function(tiddler,title) {
- $tw.utils.pushTop(results,options.wiki.getTiddlerBacktranscludes(title));
+ results.pushTop(options.wiki.getTiddlerBacktranscludes(title));
});
- return results;
+ return results.makeTiddlerIterator(options.wiki);
};
})();
diff --git a/core/modules/filters/crypto.js b/core/modules/filters/crypto.js
index 24f1a0df9..cfb524d06 100644
--- a/core/modules/filters/crypto.js
+++ b/core/modules/filters/crypto.js
@@ -14,12 +14,9 @@ Filter operators for cryptography, using the Stanford JavaScript library
exports.sha256 = function(source,operator,options) {
var results = [],
- length = parseInt(operator.operand,10) || 20,
- sha256 = function(text) {
- return sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(text)).substr(0,length);
- };
+ length = parseInt(operator.operand,10) || 20;
source(function(tiddler,title) {
- results.push(sha256(title));
+ results.push($tw.utils.sha256(title,{length: length}));
});
return results;
};
diff --git a/core/modules/filters/strings.js b/core/modules/filters/strings.js
index 538dd0597..11f7634b7 100644
--- a/core/modules/filters/strings.js
+++ b/core/modules/filters/strings.js
@@ -127,7 +127,7 @@ function diffPartsToChars(text1,text2,mode) {
if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) {
chars += String.fromCharCode(lineHash[line]);
} else {
- if (lineArrayLength == maxLines) {
+ if(lineArrayLength == maxLines) {
line = text.substring(lineStart);
lineEnd = text.length;
}
@@ -217,7 +217,10 @@ exports.splitregexp = function(source,operator,options) {
return ["RegExp error: " + ex];
}
source(function(tiddler,title) {
- Array.prototype.push.apply(result,title.split(regExp));
+ var parts = title.split(regExp).map(function(part){
+ return part || ""; // make sure it's a string
+ });
+ Array.prototype.push.apply(result,parts);
});
return result;
};
@@ -264,7 +267,7 @@ exports.pad = function(source,operator,options) {
} else {
var padString = "",
padStringLength = targetLength - title.length;
- while (padStringLength > padString.length) {
+ while(padStringLength > padString.length) {
padString += fill;
}
//make sure we do not exceed the specified length
diff --git a/core/modules/filters/transcludes.js b/core/modules/filters/transcludes.js
index bd618296b..8f42b3bae 100644
--- a/core/modules/filters/transcludes.js
+++ b/core/modules/filters/transcludes.js
@@ -20,7 +20,7 @@ exports.transcludes = function(source,operator,options) {
source(function(tiddler,title) {
results.pushTop(options.wiki.getTiddlerTranscludes(title));
});
- return results.toArray();
+ return results.makeTiddlerIterator(options.wiki);
};
})();
diff --git a/core/modules/filters/x-listops.js b/core/modules/filters/x-listops.js
index 760f581a1..ae17297a5 100644
--- a/core/modules/filters/x-listops.js
+++ b/core/modules/filters/x-listops.js
@@ -202,7 +202,7 @@ Extended filter operators to manipulate the current list.
}
if(resultsIndex !== -1) {
i = i + step;
- nextOperandIndex = (i < opLength ? i : i - opLength);
+ nextOperandIndex = (i < opLength ? i : i % opLength);
if(operands.length > 1) {
results.splice(resultsIndex,1,operands[nextOperandIndex]);
} else {
diff --git a/core/modules/indexers/back-indexer.js b/core/modules/indexers/back-indexer.js
index 609d62bfc..77b51b819 100644
--- a/core/modules/indexers/back-indexer.js
+++ b/core/modules/indexers/back-indexer.js
@@ -70,9 +70,12 @@ BackSubIndexer.prototype.rebuild = function() {
* Get things that is being referenced in the text, e.g. tiddler names in the link syntax.
*/
BackSubIndexer.prototype._getTarget = function(tiddler) {
+ if(this.wiki.isBinaryTiddler(tiddler.fields.text)) {
+ return [];
+ }
var parser = this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});
if(parser) {
- return this.wiki[this.extractor](parser.tree);
+ return this.wiki[this.extractor](parser.tree, tiddler.fields.title);
}
return [];
}
diff --git a/core/modules/macros/csvtiddlers.js b/core/modules/macros/csvtiddlers.js
index 7b34ce04d..a492fd81c 100644
--- a/core/modules/macros/csvtiddlers.js
+++ b/core/modules/macros/csvtiddlers.js
@@ -35,9 +35,11 @@ exports.run = function(filter,format) {
// Collect all the fields
for(t=0;t') {
+ tag.closeTagStart = tag.end;
+ } else {
+ tag.closeTagStart = tag.closeTagEnd - 2;
+ var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd;
+ if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
+ while (tag.closeTagStart >= closeTagMinPos) {
+ var char = this.parser.source[tag.closeTagStart];
+ if (char === '>') {
+ tag.closeTagStart = -1;
+ break;
+ }
+ if (char === '<') break;
+ tag.closeTagStart -= 1;
+ }
+ if (tag.closeTagStart < closeTagMinPos) {
+ tag.closeTagStart = tag.end;
+ }
+ }
}
// Return the tag
return [tag];
diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js
index 6b379d9c5..6f58225e0 100644
--- a/core/modules/parsers/wikiparser/rules/image.js
+++ b/core/modules/parsers/wikiparser/rules/image.js
@@ -122,9 +122,9 @@ exports.parseImage = function(source,pos) {
}
pos = token.end;
if(token.match[1]) {
- node.attributes.tooltip = {type: "string", value: token.match[1].trim()};
+ node.attributes.tooltip = {type: "string", value: token.match[1].trim(),start: token.start,end:token.start + token.match[1].length - 1};
}
- node.attributes.source = {type: "string", value: (token.match[2] || "").trim()};
+ node.attributes.source = {type: "string", value: (token.match[2] || "").trim(), start: token.start + (token.match[1] ? token.match[1].length : 0), end: token.end - 2};
// Update the end position
node.end = pos;
return node;
diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js
index a66df7057..bb1832255 100644
--- a/core/modules/parsers/wikiparser/rules/import.js
+++ b/core/modules/parsers/wikiparser/rules/import.js
@@ -38,13 +38,14 @@ exports.parse = function() {
// Parse the filter terminated by a line break
var reMatch = /(.*)(?:$|\r?\n)/mg;
reMatch.lastIndex = this.parser.pos;
+ var filterStart = this.parser.source;
var match = reMatch.exec(this.parser.source);
this.parser.pos = reMatch.lastIndex;
// Parse tree nodes to return
return [{
type: "importvariables",
attributes: {
- filter: {type: "string", value: match[1]}
+ filter: {type: "string", value: match[1], start: filterStart, end: this.parser.pos}
},
children: []
}];
diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js
index 17eab6dad..d89c201b9 100644
--- a/core/modules/parsers/wikiparser/rules/list.js
+++ b/core/modules/parsers/wikiparser/rules/list.js
@@ -74,6 +74,7 @@ exports.parse = function() {
// Match the list marker
var reMatch = /([\*#;:>]+)/mg;
reMatch.lastIndex = this.parser.pos;
+ var start = this.parser.pos;
var match = reMatch.exec(this.parser.source);
if(!match || match.index !== this.parser.pos) {
break;
@@ -94,9 +95,21 @@ exports.parse = function() {
}
// Construct the list element or reuse the previous one at this level
if(listStack.length <= t) {
- var listElement = {type: "element", tag: listInfo.listTag, children: [
- {type: "element", tag: listInfo.itemTag, children: []}
- ]};
+ var listElement = {
+ type: "element",
+ tag: listInfo.listTag,
+ children: [
+ {
+ type: "element",
+ tag: listInfo.itemTag,
+ children: [],
+ start: start,
+ end: this.parser.pos,
+ }
+ ],
+ start: start,
+ end: this.parser.pos,
+ };
// Link this list element into the last child item of the parent list item
if(t) {
var prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];
@@ -105,21 +118,33 @@ exports.parse = function() {
// Save this element in the stack
listStack[t] = listElement;
} else if(t === (match[0].length - 1)) {
- listStack[t].children.push({type: "element", tag: listInfo.itemTag, children: []});
+ listStack[t].children.push({
+ type: "element",
+ tag: listInfo.itemTag,
+ children: [],
+ start: start,
+ end: this.parser.pos,
+ });
}
}
if(listStack.length > match[0].length) {
listStack.splice(match[0].length,listStack.length - match[0].length);
}
// Process the body of the list item into the last list item
+ var classStart = this.parser.pos;
var lastListChildren = listStack[listStack.length-1].children,
lastListItem = lastListChildren[lastListChildren.length-1],
classes = this.parser.parseClasses();
+ var classEnd = this.parser.pos;
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
var tree = this.parser.parseInlineRun(/(\r?\n)/mg);
lastListItem.children.push.apply(lastListItem.children,tree);
+ lastListItem.end = this.parser.pos;
+ listStack[listStack.length-1].end = this.parser.pos;
if(classes.length > 0) {
$tw.utils.addClassToParseTreeNode(lastListItem,classes.join(" "));
+ lastListItem.attributes.class.start = classStart;
+ lastListItem.attributes.class.end = classEnd;
}
// Consume any whitespace following the list item
this.parser.skipWhitespace();
diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js
index 4c497c257..4707fa0d0 100644
--- a/core/modules/parsers/wikiparser/rules/prettyextlink.js
+++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js
@@ -96,15 +96,20 @@ exports.parseLink = function(source,pos) {
splitPos = null;
}
// Pull out the tooltip and URL
- var tooltip, URL;
+ var tooltip, URL, urlStart;
+ textNode.start = pos;
if(splitPos) {
+ urlStart = splitPos + 1;
URL = source.substring(splitPos + 1,closePos).trim();
textNode.text = source.substring(pos,splitPos).trim();
+ textNode.end = splitPos;
} else {
+ urlStart = pos;
URL = source.substring(pos,closePos).trim();
textNode.text = URL;
+ textNode.end = closePos;
}
- node.attributes.href = {type: "string", value: URL};
+ node.attributes.href = {type: "string", value: URL, start: urlStart, end: closePos};
node.attributes.target = {type: "string", value: "_blank"};
node.attributes.rel = {type: "string", value: "noopener noreferrer"};
// Update the end position
diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js
index 56a2850a3..66c19dc88 100644
--- a/core/modules/parsers/wikiparser/rules/prettylink.js
+++ b/core/modules/parsers/wikiparser/rules/prettylink.js
@@ -29,32 +29,39 @@ exports.init = function(parser) {
exports.parse = function() {
// Move past the match
+ var start = this.parser.pos + 2;
this.parser.pos = this.matchRegExp.lastIndex;
// Process the link
var text = this.match[1],
- link = this.match[2] || text;
+ link = this.match[2] || text,
+ textEndPos = this.parser.source.indexOf("|", start);
+ if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
+ textEndPos = this.matchRegExp.lastIndex - 2;
+ }
+ var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start;
+ var linkEnd = linkStart + link.length;
if($tw.utils.isLinkExternal(link)) {
return [{
type: "element",
tag: "a",
attributes: {
- href: {type: "string", value: link},
+ href: {type: "string", value: link, start: linkStart, end: linkEnd},
"class": {type: "string", value: "tc-tiddlylink-external"},
target: {type: "string", value: "_blank"},
rel: {type: "string", value: "noopener noreferrer"}
},
children: [{
- type: "text", text: text
+ type: "text", text: text, start: start, end: textEndPos
}]
}];
} else {
return [{
type: "link",
attributes: {
- to: {type: "string", value: link}
+ to: {type: "string", value: link, start: linkStart, end: linkEnd}
},
children: [{
- type: "text", text: text
+ type: "text", text: text, start: start, end: textEndPos
}]
}];
}
diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js
index 71b689680..fdd6c860b 100644
--- a/core/modules/parsers/wikiparser/rules/quoteblock.js
+++ b/core/modules/parsers/wikiparser/rules/quoteblock.js
@@ -3,30 +3,7 @@ title: $:/core/modules/parsers/wikiparser/rules/quoteblock.js
type: application/javascript
module-type: wikirule
-Wiki text rule for quote blocks. For example:
-
-```
- <<<.optionalClass(es) optional cited from
- a quote
- <<<
-
- <<<.optionalClass(es)
- a quote
- <<< optional cited from
-```
-
-Quotes can be quoted by putting more 0) {
tree.unshift({
type: "element",
tag: "cite",
- children: cite
+ children: cite,
+ start: citeStart,
+ end: citeEnd
});
}
// Parse any optional cite
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
+ citeStart = this.parser.pos;
cite = this.parser.parseInlineRun(/(\r?\n)/mg);
+ citeEnd = this.parser.pos;
// If we got a cite, push it
if(cite.length > 0) {
tree.push({
type: "element",
tag: "cite",
- children: cite
+ children: cite,
+ start: citeStart,
+ end: citeEnd
});
}
// Return the blockquote element
@@ -81,7 +67,7 @@ exports.parse = function() {
type: "element",
tag: "blockquote",
attributes: {
- class: { type: "string", value: classes.join(" ") },
+ class: { type: "string", value: classes.join(" "), start: classStart, end: classEnd },
},
children: tree
}];
diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js
index 6eb2cdcd4..6bcbee384 100644
--- a/core/modules/parsers/wikiparser/rules/syslink.js
+++ b/core/modules/parsers/wikiparser/rules/syslink.js
@@ -29,10 +29,11 @@ exports.init = function(parser) {
exports.parse = function() {
var match = this.match[0];
// Move past the match
+ var start = this.parser.pos;
this.parser.pos = this.matchRegExp.lastIndex;
// Create the link unless it is suppressed
if(match.substr(0,1) === "~") {
- return [{type: "text", text: match.substr(1)}];
+ return [{type: "text", text: match.substr(1), start: start+1, end: this.parser.pos}];
} else {
return [{
type: "link",
@@ -41,10 +42,12 @@ exports.parse = function() {
},
children: [{
type: "text",
- text: match
+ text: match,
+ start: start,
+ end: this.parser.pos
}]
}];
}
};
-})();
\ No newline at end of file
+})();
diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js
index 61cd71948..fbdbb4f9d 100644
--- a/core/modules/parsers/wikiparser/rules/table.js
+++ b/core/modules/parsers/wikiparser/rules/table.js
@@ -93,11 +93,12 @@ var processRow = function(prevColumns) {
}
// Check whether this is a heading cell
var cell;
+ var start = this.parser.pos;
if(chr === "!") {
this.parser.pos++;
- cell = {type: "element", tag: "th", children: []};
+ cell = {type: "element", tag: "th", start: start, children: []};
} else {
- cell = {type: "element", tag: "td", children: []};
+ cell = {type: "element", tag: "td", start: start, children: []};
}
tree.push(cell);
// Record information about this cell
@@ -121,6 +122,7 @@ var processRow = function(prevColumns) {
}
// Move back to the closing `|`
this.parser.pos--;
+ cell.end = this.parser.pos;
}
col++;
cellRegExp.lastIndex = this.parser.pos;
@@ -150,7 +152,7 @@ exports.parse = function() {
} else {
// Otherwise, create a new row if this one is of a different type
if(rowType !== currRowType) {
- rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: []};
+ rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: [], start: this.parser.pos, end: this.parser.pos};
table.children.push(rowContainer);
currRowType = rowType;
}
@@ -169,15 +171,17 @@ exports.parse = function() {
rowContainer.children = this.parser.parseInlineRun(rowTermRegExp,{eatTerminator: true});
} else {
// Create the row
- var theRow = {type: "element", tag: "tr", children: []};
+ var theRow = {type: "element", tag: "tr", children: [], start: rowMatch.index};
$tw.utils.addClassToParseTreeNode(theRow,rowCount%2 ? "oddRow" : "evenRow");
rowContainer.children.push(theRow);
// Process the row
theRow.children = processRow.call(this,prevColumns);
this.parser.pos = rowMatch.index + rowMatch[0].length;
+ theRow.end = this.parser.pos;
// Increment the row count
rowCount++;
}
+ rowContainer.end = this.parser.pos;
}
rowMatch = rowRegExp.exec(this.parser.source);
}
diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js
index 4195e57e5..07c88be15 100644
--- a/core/modules/parsers/wikiparser/rules/typedblock.js
+++ b/core/modules/parsers/wikiparser/rules/typedblock.js
@@ -46,6 +46,7 @@ exports.parse = function() {
renderType = this.match[2];
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
+ var start = this.parser.pos;
// Look for the end of the block
reEnd.lastIndex = this.parser.pos;
var match = reEnd.exec(this.parser.source),
@@ -74,7 +75,9 @@ exports.parse = function() {
tag: "pre",
children: [{
type: "text",
- text: text
+ text: text,
+ start: start,
+ end: this.parser.pos
}]
}];
}
diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js
index fadc4587e..6b195f9ff 100644
--- a/core/modules/parsers/wikiparser/rules/wikilink.js
+++ b/core/modules/parsers/wikiparser/rules/wikilink.js
@@ -36,6 +36,7 @@ exports.parse = function() {
// Get the details of the match
var linkText = this.match[0];
// Move past the macro call
+ var start = this.parser.pos;
this.parser.pos = this.matchRegExp.lastIndex;
// If the link starts with the unwikilink character then just output it as plain text
if(linkText.substr(0,1) === $tw.config.textPrimitives.unWikiLink) {
@@ -57,7 +58,9 @@ exports.parse = function() {
},
children: [{
type: "text",
- text: linkText
+ text: linkText,
+ start: start,
+ end: this.parser.pos
}]
}];
};
diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
index 527e39eba..854171d19 100644
--- a/core/modules/parsers/wikiparser/wikiparser.js
+++ b/core/modules/parsers/wikiparser/wikiparser.js
@@ -91,6 +91,11 @@ var WikiParser = function(type,text,options) {
} else {
topBranch.push.apply(topBranch,this.parseBlocks());
}
+ // Build rules' name map
+ this.usingRuleMap = {};
+ $tw.utils.each(this.pragmaRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
+ $tw.utils.each(this.blockRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
+ $tw.utils.each(this.inlineRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
// Return the parse tree
};
@@ -209,8 +214,13 @@ WikiParser.prototype.parsePragmas = function() {
break;
}
// Process the pragma rule
+ var start = this.pos;
var subTree = nextMatch.rule.parse();
if(subTree.length > 0) {
+ // Set the start and end positions of the pragma rule if
+ if (subTree[0].start === undefined) subTree[0].start = start;
+ if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
+ $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment
currentTreeBranch.push.apply(currentTreeBranch,subTree);
subTree[0].children = [];
@@ -235,7 +245,15 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
// Look for a block rule that applies at the current position
var nextMatch = this.findNextMatch(this.blockRules,this.pos);
if(nextMatch && nextMatch.matchIndex === this.pos) {
- return nextMatch.rule.parse();
+ var start = this.pos;
+ var subTree = nextMatch.rule.parse();
+ // Set the start and end positions of the first and last blocks if they're not already set
+ if (subTree.length > 0) {
+ if (subTree[0].start === undefined) subTree[0].start = start;
+ if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
+ }
+ $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
+ return subTree;
}
// Treat it as a paragraph if we didn't find a block rule
var start = this.pos;
@@ -332,7 +350,16 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
this.pos = nextMatch.matchIndex;
}
// Process the run rule
- tree.push.apply(tree,nextMatch.rule.parse());
+ var start = this.pos;
+ var subTree = nextMatch.rule.parse();
+ // Set the start and end positions of the first and last child if they're not already set
+ if (subTree.length > 0) {
+ // Set the start and end positions of the first and last child if they're not already set
+ if (subTree[0].start === undefined) subTree[0].start = start;
+ if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
+ }
+ $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
+ tree.push.apply(tree,subTree);
// Look for the next run rule
nextMatch = this.findNextMatch(this.inlineRules,this.pos);
}
@@ -383,7 +410,15 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx
this.pos = inlineRuleMatch.matchIndex;
}
// Process the inline rule
- tree.push.apply(tree,inlineRuleMatch.rule.parse());
+ var start = this.pos;
+ var subTree = inlineRuleMatch.rule.parse();
+ // Set the start and end positions of the first and last child if they're not already set
+ if (subTree.length > 0) {
+ if (subTree[0].start === undefined) subTree[0].start = start;
+ if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
+ }
+ $tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; });
+ tree.push.apply(tree,subTree);
// Look for the next inline rule
inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);
// Look for the next terminator match
@@ -409,7 +444,7 @@ WikiParser.prototype.pushTextWidget = function(array,text,start,end) {
text = $tw.utils.trim(text);
}
if(text) {
- array.push({type: "text", text: text, start: start, end: end});
+ array.push({type: "text", text: text, start: start, end: end});
}
};
@@ -462,4 +497,3 @@ WikiParser.prototype.amendRules = function(type,names) {
exports["text/vnd.tiddlywiki"] = WikiParser;
})();
-
diff --git a/core/modules/saver-handler.js b/core/modules/saver-handler.js
index 119c3e67a..23056bcc2 100644
--- a/core/modules/saver-handler.js
+++ b/core/modules/saver-handler.js
@@ -95,6 +95,7 @@ function SaverHandler(options) {
if($tw.browser) {
$tw.rootWidget.addEventListener("tm-save-wiki",function(event) {
self.saveWiki({
+ wiki: event.widget.wiki,
template: event.param,
downloadType: "text/plain",
variables: event.paramObject
@@ -102,6 +103,7 @@ function SaverHandler(options) {
});
$tw.rootWidget.addEventListener("tm-download-file",function(event) {
self.saveWiki({
+ wiki: event.widget.wiki,
method: "download",
template: event.param,
downloadType: "text/plain",
@@ -147,20 +149,22 @@ Save the wiki contents. Options are:
method: "save", "autosave" or "download"
template: the tiddler containing the template to save
downloadType: the content type for the saved file
+ wiki: optional wiki, overriding the default wiki specified in the constructor
*/
SaverHandler.prototype.saveWiki = function(options) {
options = options || {};
var self = this,
+ wiki = options.wiki || this.wiki,
method = options.method || "save";
// Ignore autosave if disabled
- if(method === "autosave" && ($tw.config.disableAutoSave || this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes")) {
+ if(method === "autosave" && ($tw.config.disableAutoSave || wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes")) {
return false;
}
var variables = options.variables || {},
template = (options.template ||
- this.wiki.getTiddlerText("$:/config/SaveWikiButton/Template","$:/core/save/all")).trim(),
+ wiki.getTiddlerText("$:/config/SaveWikiButton/Template","$:/core/save/all")).trim(),
downloadType = options.downloadType || "text/plain",
- text = this.wiki.renderTiddler(downloadType,template,options),
+ text = wiki.renderTiddler(downloadType,template,options),
callback = function(err) {
if(err) {
alert($tw.language.getString("Error/WhileSaving") + ":\n\n" + err);
diff --git a/core/modules/savers/put.js b/core/modules/savers/put.js
index de9ba9465..a1ebef4bb 100644
--- a/core/modules/savers/put.js
+++ b/core/modules/savers/put.js
@@ -48,7 +48,7 @@ var PutSaver = function(wiki) {
var self = this;
var uri = this.uri();
// Async server probe. Until probe finishes, save will fail fast
- // See also https://github.com/Jermolene/TiddlyWiki5/issues/2276
+ // See also https://github.com/TiddlyWiki/TiddlyWiki5/issues/2276
$tw.utils.httpRequest({
url: uri,
type: "OPTIONS",
diff --git a/core/modules/server/authenticators/header.js b/core/modules/server/authenticators/header.js
index 9d9990d31..cc1d6bdaf 100644
--- a/core/modules/server/authenticators/header.js
+++ b/core/modules/server/authenticators/header.js
@@ -37,7 +37,9 @@ HeaderAuthenticator.prototype.authenticateRequest = function(request,response,st
return false;
} else {
// authenticatedUsername will be undefined for anonymous users
- state.authenticatedUsername = $tw.utils.decodeURIComponentSafe(username);
+ if(username) {
+ state.authenticatedUsername = $tw.utils.decodeURIComponentSafe(username);
+ }
return true;
}
};
diff --git a/core/modules/server/server.js b/core/modules/server/server.js
index 258ddfa31..d3c98f8fc 100644
--- a/core/modules/server/server.js
+++ b/core/modules/server/server.js
@@ -140,6 +140,11 @@ function sendResponse(request,response,statusCode,headers,data,encoding) {
return;
}
}
+ } else {
+ // RFC 7231, 6.1. Overview of Status Codes:
+ // Browser clients may cache 200, 203, 204, 206, 300, 301,
+ // 404, 405, 410, 414, and 501 unless given explicit cache controls
+ headers["Cache-Control"] = headers["Cache-Control"] || "no-store";
}
/*
If the gzip=yes is set, check if the user agent permits compression. If so,
diff --git a/core/modules/startup/plugins.js b/core/modules/startup/plugins.js
index ab74214b9..fc8ba9589 100644
--- a/core/modules/startup/plugins.js
+++ b/core/modules/startup/plugins.js
@@ -61,7 +61,7 @@ exports.startup = function() {
// Collect the shadow tiddlers of any modified plugins
$tw.utils.each(changes.modifiedPlugins,function(pluginTitle) {
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
- if(pluginInfo) {
+ if(pluginInfo && pluginInfo.tiddlers) {
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
changedShadowTiddlers[title] = false;
});
diff --git a/core/modules/startup/render.js b/core/modules/startup/render.js
index e50512463..7206a51d0 100644
--- a/core/modules/startup/render.js
+++ b/core/modules/startup/render.js
@@ -29,7 +29,11 @@ var THROTTLE_REFRESH_TIMEOUT = 400;
exports.startup = function() {
// Set up the title
- $tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});
+ $tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE, {
+ document: $tw.fakeDocument,
+ parseAsInline: true,
+ importPageMacros: true,
+ });
$tw.titleContainer = $tw.fakeDocument.createElement("div");
$tw.titleWidgetNode.render($tw.titleContainer,null);
document.title = $tw.titleContainer.textContent;
@@ -81,6 +85,8 @@ exports.startup = function() {
deferredChanges = Object.create(null);
$tw.hooks.invokeHook("th-page-refreshed");
}
+ var throttledRefresh = $tw.perf.report("throttledRefresh",refresh);
+
// Add the change event handler
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
// Check if only tiddlers that are throttled have changed
@@ -101,7 +107,7 @@ exports.startup = function() {
if(isNaN(timeout)) {
timeout = THROTTLE_REFRESH_TIMEOUT;
}
- timerId = setTimeout(refresh,timeout);
+ timerId = setTimeout(throttledRefresh,timeout);
$tw.utils.extend(deferredChanges,changes);
} else {
$tw.utils.extend(deferredChanges,changes);
diff --git a/core/modules/startup/rootwidget.js b/core/modules/startup/rootwidget.js
index 716275cda..d81e07aee 100644
--- a/core/modules/startup/rootwidget.js
+++ b/core/modules/startup/rootwidget.js
@@ -39,6 +39,7 @@ exports.startup = function() {
method: params.method,
body: params.body,
binary: params.binary,
+ useDefaultHeaders: params.useDefaultHeaders,
oncompletion: params.oncompletion,
onprogress: params.onprogress,
bindStatus: params["bind-status"],
@@ -47,7 +48,11 @@ exports.startup = function() {
headers: getPropertiesWithPrefix(params,"header-"),
passwordHeaders: getPropertiesWithPrefix(params,"password-header-"),
queryStrings: getPropertiesWithPrefix(params,"query-"),
- passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-")
+ passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-"),
+ basicAuthUsername: params["basic-auth-username"],
+ basicAuthUsernameFromStore: params["basic-auth-username-from-store"],
+ basicAuthPassword: params["basic-auth-password"],
+ basicAuthPasswordFromStore: params["basic-auth-password-from-store"]
});
});
$tw.rootWidget.addEventListener("tm-http-cancel-all-requests",function(event) {
@@ -68,7 +73,10 @@ exports.startup = function() {
});
// Install the copy-to-clipboard mechanism
$tw.rootWidget.addEventListener("tm-copy-to-clipboard",function(event) {
- $tw.utils.copyToClipboard(event.param);
+ $tw.utils.copyToClipboard(event.param,{
+ successNotification: event.paramObject && event.paramObject.successNotification,
+ failureNotification: event.paramObject && event.paramObject.failureNotification
+ });
});
// Install the tm-focus-selector message
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
diff --git a/core/modules/startup/story.js b/core/modules/startup/story.js
index 734f6ae76..c58c759c3 100644
--- a/core/modules/startup/story.js
+++ b/core/modules/startup/story.js
@@ -93,7 +93,9 @@ exports.startup = function() {
updateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,"yes").trim() === "yes" ? "permalink" : "none",
updateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,"no").trim(),
targetTiddler: event.param || event.tiddlerTitle,
- copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permalink" : "none"
+ copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permalink" : "none",
+ successNotification: event.paramObject && event.paramObject.successNotification,
+ failureNotification: event.paramObject && event.paramObject.failureNotification
});
});
// Listen for the tm-permaview message
@@ -102,7 +104,9 @@ exports.startup = function() {
updateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,"yes").trim() === "yes" ? "permaview" : "none",
updateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,"no").trim(),
targetTiddler: event.param || event.tiddlerTitle,
- copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permaview" : "none"
+ copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permaview" : "none",
+ successNotification: event.paramObject && event.paramObject.successNotification,
+ failureNotification: event.paramObject && event.paramObject.failureNotification
});
});
}
@@ -177,6 +181,8 @@ options.updateAddressBar: "permalink", "permaview" or "no" (defaults to "permavi
options.updateHistory: "yes" or "no" (defaults to "no")
options.copyToClipboard: "permalink", "permaview" or "no" (defaults to "no")
options.targetTiddler: optional title of target tiddler for permalink
+options.successNotification: optional title of tiddler to use as the notification in case of success
+options.failureNotification: optional title of tiddler to use as the notification in case of failure
*/
function updateLocationHash(options) {
// Get the story and the history stack
@@ -205,14 +211,18 @@ function updateLocationHash(options) {
break;
}
// Copy URL to the clipboard
+ var url = "";
switch(options.copyToClipboard) {
case "permalink":
- $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler));
+ url = $tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler);
break;
case "permaview":
- $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList)));
+ url = $tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList));
break;
}
+ if(url) {
+ $tw.utils.copyToClipboard(url,{successNotification: options.successNotification, failureNotification: options.failureNotification});
+ }
// Only change the location hash if we must, thus avoiding unnecessary onhashchange events
if($tw.utils.getLocationHash() !== $tw.locationHash) {
if(options.updateHistory === "yes") {
diff --git a/core/modules/startup/windows.js b/core/modules/startup/windows.js
index aa9f982ed..34f45d7a5 100644
--- a/core/modules/startup/windows.js
+++ b/core/modules/startup/windows.js
@@ -56,7 +56,7 @@ exports.startup = function() {
return;
}
// Initialise the document
- srcDocument.write("");
+ srcDocument.write("