Compare commits
44 Commits
new-releas
...
docs-make-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1a8b56124 | ||
|
|
88b472c955 | ||
|
|
8c956a9448 | ||
|
|
4bb0bc5527 | ||
|
|
3378497816 | ||
|
|
d81204c6ab | ||
|
|
e001c21bf5 | ||
|
|
102c236267 | ||
|
|
06a2923adf | ||
|
|
54e5ef7489 | ||
|
|
6f306d1ed6 | ||
|
|
5dfdbc8ea0 | ||
|
|
4d4d9d9995 | ||
|
|
bad87c405e | ||
|
|
6f23a078b7 | ||
|
|
c3706b8a79 | ||
|
|
7ca8fb29af | ||
|
|
d39bb5274e | ||
|
|
81b69783c4 | ||
|
|
b349adde16 | ||
|
|
d63a1896b3 | ||
|
|
b65fa11643 | ||
|
|
4043499633 | ||
|
|
6a39a4e13b | ||
|
|
5b5147dade | ||
|
|
2c8fafee48 | ||
|
|
09a42a54c0 | ||
|
|
f4f31c37fc | ||
|
|
ed3405672a | ||
|
|
e3af967cbb | ||
|
|
6b0d3fab5d | ||
|
|
13f1689e7e | ||
|
|
4c09a88272 | ||
|
|
3c1d658fad | ||
|
|
5d738673ac | ||
|
|
7c020d0eb6 | ||
|
|
a2e5c2cca2 | ||
|
|
5ff4e02a61 | ||
|
|
2cc7c96eec | ||
|
|
8cd3d4e22c | ||
|
|
37e09d1c25 | ||
|
|
7a080092d0 | ||
|
|
dd91ac0b82 | ||
|
|
c22046a2c2 |
@@ -6,6 +6,7 @@ talk.tiddlywiki.org: jeremyruston
|
||||
github: Jermolene
|
||||
linkedin: www.linkedin.com/in/jermy
|
||||
flickr: www.flickr.com/photos/jermy/
|
||||
bluesky: https://bsky.app/profile/jermolene.bsky.social
|
||||
homepage: jermolene.com
|
||||
email: jeremy@jermolene.com
|
||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAtAAEBAAMAAAAAAAAAAAAAAAAHBgIEBQEBAQEBAAAAAAAAAAAAAAAAAgQBBf/aAAwDAQACEAMQAAAANF4uTuPRhD2nBLnUiJvKM0DtMKy//8QAKxAAAgIBAwMDAQkAAAAAAAAAAQIDBBEABRITITEiMkFxFEJRUmFicoGR/9oACAEBAAE/AInTA6gUGP4ZOQbW1bPsmyUq1q+gmvFPUzZPDkPamtwqU75ks04JakroVcg5RwRjg66NUx25KbzqJYyMngfqSuq0M3NZYIebJIvZozIvI/iNPcp/aalSdJXsS4VcKeIzlvU3jVTcYLNiaGISrjkhWQYDfQ63pYAzCDBsOiu7Dsx4EHH6r2w2ttimjd2IsNErhhJHKI04/uzqxuCxpBYVVWKSHqwMyMSQ33SB7dUJFmlkMYRgnqZgCMf7rf8AeEt3A9YOhjXAb2k8u7dtT1RZeOtXmYxiOPj4ZWY/lb51skqUNnNW/wBNzC7IpB6gQeeB/jq/fqGOaLbowuYn5MAQOw8LjW5Vmeo0qIsqYLLKjHIZmwv9fB1//8QAHxEAAQMEAwEAAAAAAAAAAAAAEQABAgMSIWExMkFR/9oACAECAQE/AD9iTy2lJmHUB8BVKM4SNSOj46a29saX/8QAHREAAgICAwEAAAAAAAAAAAAAAQIAAwQRITGBkf/aAAgBAwEBPwDHpFpJZtamVSiBWT2Yt7hmCDsb+TKtsKqpGg3M/9k=
|
||||
|
||||
19
community/people/LinOnetwo.tid
Normal file
@@ -0,0 +1,19 @@
|
||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEAAwEBAAAAAAAAAAAAAAAGAwQHAgUBAAMBAAAAAAAAAAAAAAAAAAACAwT/2gAMAwEAAhADEAAAAOfCWAMdKKetM4wOvY5OcvZnrYf/xAApEAACAQQBBAECBwAAAAAAAAABAgMABAURQQYSIVETFCIxMkJicYKh/9oACAEBAAE/AEtysaStr7mPaPeuazWdMM4gEnfPryW8hBUuZvou2RXRxyreBWPmgyNqs8f8MOQalhdY7Vz+R4/s/qfP+1edNi/zl7HDcFbmS3E8CcMR4INP0PkBhklIm+sZNtFtQiV0nj57Owl+dSrSTFgD6/CtH4VV9lU3oAbPngAVY389lc5URuUZkMxhnR4pvW0VwDqsP1FNmLWYqCpikMbngmliJNY+aKzyTxXS6lRAyg/u5rq+5x2RsuyTa3MQMlvKniRGThTUd1JYXUdzAwDvqVxGdRXMbfrVOD7HBrG3mNEsU8z98TRhl9eRzX//xAAcEQACAgIDAAAAAAAAAAAAAAABAgARAzESIVH/2gAIAQIBAT8ARuXZPsul3Eoje5lBQWBP/8QAGREAAwEBAQAAAAAAAAAAAAAAAAECEiER/9oACAEDAQE/AM98Lk7LJe20z//Z
|
||||
created: 20251110102157310
|
||||
first-sighting: 2019-03-01
|
||||
fullname: Lin Onetwo
|
||||
github: linonetwo
|
||||
homepage: https://wiki.onetwo.website/
|
||||
modified: 20251111184556193
|
||||
tags: Community/Person Community/Team/Contributors
|
||||
talk.tiddlywiki.org: linonetwo
|
||||
title: @linonetwo
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Since 2014, when I started college, I've been on a quest for a lifelong PKM tool. I cherish my life and all my experiences, and I don’t want to forget any of them. When I’m deeply focused on a task, it’s easy to lose sight of other important parts of my life—so I needed a system to help me stay balanced.
|
||||
|
||||
Early on, I tried TiddlyWiki several times, but I was initially put off by its save mechanism and markup editing. That changed when I discovered an auto-backup script, which gave me the confidence to fully commit. Over time, I improved the script and eventually transitioned to using TidGi-Desktop and TidGi-Mobile.
|
||||
|
||||
Today, my TiddlyWiki holds all my game design ideas and progress logs—it has truly become my second brain. With the help of LLM-powered programming tools, I’ve enhanced it with numerous plugins, allowing me to manage my mind in a more programmable and structured way. As a game developer, TiddlyWiki isn't the core of my professional work; But I've invested so much time because it's fundamentally about upgrading my mind.
|
||||
|
||||
Most of my notes are open by default and shared publicly on my homepage as a digital garden.
|
||||
25
community/people/PMario.tid
Normal file
@@ -0,0 +1,25 @@
|
||||
avatar: UklGRiwIAABXRUJQVlA4WAoAAAAwAAAAPwAAPwAASUNDUCACAAAAAAIgbGNtcwRAAABtbnRyR1JBWVhZWiAH6QALAAoACwADAAZhY3NwTVNGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZkZXNjAAAAzAAAAG5jcHJ0AAABPAAAADZ3dHB0AAABdAAAABRrVFJDAAABiAAAACBkbW5kAAABqAAAACRkbWRkAAABzAAAAFJtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFIAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA81EAAQAAAAEWzHBhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbbWx1YwAAAAAAAAABAAAADGVuVVMAAAAIAAAAHABHAEkATQBQbWx1YwAAAAAAAAABAAAADGVuVVMAAAA2AAAAHABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAVlA4TOYFAAAvP8APEDWGgbRtWv+yt/0WImICOBvWn1C4dFi1bStbvpY8Qg2ePANNNAMh3N2db/7A91/7CHBvBBRr25ZFH+4k98ihkqi2CP4tsANvX8a+8y8Ct04dn0nuUt39ZiBJkowqt911M+MJ1G3bNiZJr1iP0DZ+2bbdadsqprOjAqmoUIX9hf3Fl5/uPYV7I3OMeoFzIvrvwG0kRUr3zPLdYMMXaqrMMsp0K4fufKO6c2hFV5Zh7kRROZX0PSCmB/3KWQwpuiekWelSRZDW94d0q750NrxavpFn1eLNQ9EV8nWlmAET6Q8lrCRTcjFLlLImluK3iXJW/hT47KGklS8OlzWUtXLFYDRCSS74ojUjxggqKMoxd6A1lTCyvsvyzC5/d7BsCHb7yIcHyrX2yR/NPnsAdRT2i0Pwp/o0Il6ix8hsRAuJmQgcr4KREfAiMgUVm9KqmfSxL5pOJspVwwTiV6jiIAg1RMhHpERhbvwgGI34Hc49T7UeKZtXwEqJ+BAaoBneperJH0POs1u4dufwv8Gf+qcOfjyvX6ZIVgxE0Rw87YF3BSc9c7jsXfdjOBG7FwmSb39pfGRwu8IuvUjJNoTpFzkEvDg6W3Qt/9nf99ZXPy8HM43IweTKyNR+WVatXcWWyakBksj9cqW+QetplcjsKElvZH/zuOO/PrCx//tL3/6x/O/C1PZZvSKuulLcS4l8M1ewGPR6ef5sllXW2eGQZ7hVSEZiPmcqrSS8e2ElX8o7t1fvB9LFetmEx5hx1Xuye2PpfjZnSjj7QfKTB3bZZo05Zvh6YuivX24cpc8+ddvADWG9odrSwFalVurxUiidDHmTiaoNkkh2gjbcpxMiAbd39aVP119/N9k4+euNKfcNjwaPhZEuUupUsJrHchw1LkPrRC9bQKa3M8Mj/xx903drdnHMpbirj1ENsUre0oo3N+7gat+2ZctKdsIUYc21sRu+Ucdhn+P7DyarftW00iu3Tmbv+hTfdCTmyaIPT4PrYZDFtBN2W8S9m4oTB5Z2P3Oe7weKjVBq86kXX/r0+WuvTAzfjqm1hsYRPWlbxm4n3IaeGOJEizv8orH9w5ejjmSrfOuEq/HxT6eDemtsZ/HTvvG1/8iVspxZILrlkz/cdsIbIroOgJileFSty2xiHNW5t9fbHJ3ze87bp5T9vc8RuqMB0ReDSt464R/BJxspvgpEsrVAJMTsYg2QovPTOHrvQ9et/S2Xx+40z7dY4JBX0Pz/ElH/T73U2DkK8EiqC9hM/zV3frQfzjaAqO16s1l6xCUXnBFlYxyIer3eEdth7u5xsHKxWoGLqzY3wIULt9G3K6soei9jZ+UcF+Ka3M/II9EUWrJ/LLxy+Q9xIh0vOl3NZCrVnBsuFUTOSnJnSioRWZ9q4g+ZDk5XVORoW2qX2hbIkna3JOrdR3jmpHVLovUkLES6grRO010u0GkDlX7SpH1DQ64Wl2zaSUJv1Mtti2G7kx5IyftWMhfDlGClcxvIUhP5crhp9LIb1Vne187oSAWxelcR/kXjYQTZboW+Oj1pqF0gmfZhSDD6bSgzGWrw3s7QLNtCV+2uatYrd/aFtjDI8R52e/DdyKgRKXBhEak3Ev50+GCUA9EFUor39htVMxmWvW8AM6ptG416rZvdWn+MarIEyH5r6ruZSrx8XrWDP370vbfTjqpmZGIbiFPFoihc4jcrlYi9p3ndSuymZ+XLaKza/P/HUWHn5Axdkd9OjBskY0+pIlz4AlFPFs+aStK5PBIRR4MVVJDihsy4JdEA4pVcrVqMZDyL2/8aYocikEAR9Xjc1BNG9zEiJG7n/cGyrtnblkClBhEgMW4Kx21BEBGJjLa0hcOGmTK64KsKLfKr9QyQELclxY3hqowTIZKdZNTSS5BWiBPlKxDWBVSS41bOepkhTkhGDajLfLyUBOKlkMHPgOhx3JoRN/cEiRgSWdgF2yCyDQu4IcbNo8ftTzxveOJ5y+h509h52+h549h569h587/M20f/b1AB
|
||||
created: 20251110102157310
|
||||
first-sighting: 2009-11-14
|
||||
fullname: Mario Pietsch
|
||||
github: pmario
|
||||
homepage: https://wikilabs.github.io/
|
||||
modified: 20251110124935183
|
||||
tags: Community/Person Community/Team/Contributors
|
||||
talk.tiddlywiki.org: pmario
|
||||
title: @pmario
|
||||
type: text/vnd.tiddlywiki
|
||||
youtube: https://www.youtube.com/@pmario
|
||||
|
||||
''Hi, My name is Mario Pietsch''. Back in 2009 I was ''searching'' for ''a simple presentation tool'' and discovered ~TiddlyWiki Classic, Monkey Pirate ~TiddlyWiki ([[MPTW|https://mptw.tiddlyspot.com/]]) with ~TagglyTagging, Eric Shulman's ~TiddlyTools, Saq Imtiaz's navigation macros, and more. --- ''I was captivated''.
|
||||
|
||||
After a deep dive, I combined these elements into my own "Presentation Manager", along [[3 step by step tutorials|https://groups.google.com/g/tiddlywiki/c/qG_tZ1x0MEU/m/-vLA0luMicYJ]] to help others build it.
|
||||
|
||||
Thanks to ''the positive spirit'' of the ~TiddlyWiki community, I am proud to be part of it since 2009.
|
||||
|
||||
When Jeremy started developing ~TiddlyWiki 5 on ~GitHub, I joined in—opening [[issue no. 1|https://github.com/TiddlyWiki/TiddlyWiki5/issues/1]] all the way up to 13. For what that’s good ;) Since then, I have submitted nearly 600 pull requests and more than 500 issues, many of which have been merged or resolved.
|
||||
|
||||
My ~TiddlyWiki 5 "laboratory" is at https://wikilabs.github.io, and I also share content on my ''~YouTube'' channel: https://www.youtube.com/@pmario
|
||||
|
||||
Have fun!<br>
|
||||
Mario
|
||||
19
community/project/teams/Developer Experience Team.tid
Normal file
@@ -0,0 +1,19 @@
|
||||
title: Developer Experience Team
|
||||
tags: Community/Team
|
||||
modified: 20251109200632671
|
||||
created: 20251109200632671
|
||||
leader: @pmario
|
||||
team: @saqimtiaz
|
||||
|
||||
The Developer Experience Team improves the experience of software contributors to the TiddlyWiki project. This includes enhancing documentation, streamlining contribution processes, and providing tools and resources to help developers effectively contribute to TiddlyWiki.
|
||||
|
||||
Tools and resources managed by the Developer Experience Team include:
|
||||
|
||||
* Advising and assisting contributors, particularly new developers
|
||||
* Maintenance of developer-focused documentation on the https://tiddlywiki.com/dev/ site, including:
|
||||
** Development environment setup guides
|
||||
** Code review processes and best practices
|
||||
** Contribution guidelines and documentation
|
||||
* Continuous integration and deployment scripts providing feedback on pull requests
|
||||
* Devising and implementing labelling systems for issues and pull requests
|
||||
* Automation scripts to simplify common development tasks
|
||||
@@ -1,8 +1,8 @@
|
||||
title: Infrastructure Team
|
||||
tags: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
modified: 20251110133437795
|
||||
tags: Community/Team
|
||||
team: @MotovunJack
|
||||
title: Infrastructure Team
|
||||
|
||||
The Infrastructure Team is responsible for maintaining and improving the infrastructure that supports the TiddlyWiki project. This includes the hosting, deployment, and management of the TiddlyWiki websites and services, as well as the tools and systems used by the TiddlyWiki community.
|
||||
|
||||
@@ -12,3 +12,4 @@ The infrastructure includes:
|
||||
* github.com/TiddlyWiki
|
||||
* tiddlywiki.com DNS
|
||||
* Netlify account for PR previews
|
||||
* edit.tiddlywiki.com
|
||||
11
community/project/teams/Quality Assurance Team.tid
Normal file
@@ -0,0 +1,11 @@
|
||||
title: Quality Assurance Team
|
||||
created: 20251112125742296
|
||||
modified: 20251112125742296
|
||||
tags: Community/Team
|
||||
team:
|
||||
leader: @Leilei332
|
||||
|
||||
title: Quality Assurance Team
|
||||
|
||||
The Quality Assurance Team is responsible for ensuring the quality and reliability of TiddlyWiki releases. This includes reviewing code submissions, testing new features, identifying bugs, and verifying that fixes are effective.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
title: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Infrastructure Team]] [[Succession Team]]
|
||||
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[Quality Assurance Team]] [[Infrastructure Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Succession Team]]
|
||||
|
||||
|
||||
127
editions/dev/tiddlers/How to Create a Custom Cascade Entry.tid
Normal file
@@ -0,0 +1,127 @@
|
||||
created: 20240802065815656
|
||||
modified: 20240802065836064
|
||||
title: How to Create a Custom Cascade Entry
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This guide explains how to add a new [[cascade|https://tiddlywiki.com/#Cascades]] to the ~TiddlyWiki core or your own plugins. This allows third-party plugins to extend the functionality of the core or your plugin.
|
||||
|
||||
!! How Cascade Works in the Core
|
||||
|
||||
This section explains how the existing WikiText in the core interacts with the new WikiText you’ll add, only for learning purpose. You don’t need to modify the core WikiText when adding a new cascade.
|
||||
|
||||
!!! The Default Template as a Fallback
|
||||
|
||||
The default behavior in ~TiddlyWiki is defined by [[$:/core/ui/ViewTemplate/tags/default]].
|
||||
|
||||
<pre>
|
||||
<$view tiddler="$:/core" subtiddler="$:/core/ui/ViewTemplate/tags/default" mode=block format=text/>
|
||||
</pre>
|
||||
|
||||
!!! Transclusion of the Active Template
|
||||
|
||||
[[$:/core/ui/ViewTemplate/tags]] uses a filter expression to find the cascade filter and the view template you’ll add.
|
||||
|
||||
<pre>
|
||||
<$view tiddler="$:/core" subtiddler="$:/core/ui/ViewTemplate/tags" mode=block format=text/>
|
||||
</pre>
|
||||
|
||||
The `:cascade` clause collects all tiddlers it finds and uses their filter text sequentially. Most filters won’t return any text and will be skipped. The first filter that returns a tiddler title becomes the result of the `:cascade` clause. If no filters return a result, the fallback default filter will be used.
|
||||
|
||||
The `:and[!is[blank]else` clause provides additional fallback protection, though it’s often redundant because a fallback is typically tagged with `$:/tags/ViewTemplateTagsFilter`. However, including fallbacks is a good practice for defensive programming.
|
||||
|
||||
!! Adding a New Cascade Entry
|
||||
|
||||
This section contains the WikiText you’ll need to add to the core. Modify it to suit your needs instead of copying it directly.
|
||||
|
||||
!!! Creating a Control Panel Tab
|
||||
|
||||
To create a new tab under [[ControlPanel|$:/ControlPanel]] → Advanced → [[Cascade|$:/core/ui/ControlPanel/Cascades]], use the following code:
|
||||
|
||||
[[$:/core/ui/ControlPanel/ViewTemplateTags]] uses a filter expression to find the cascade filter and the view template you’ll add.
|
||||
|
||||
<pre>
|
||||
<$view tiddler="$:/core" subtiddler="$:/core/ui/ControlPanel/ViewTemplateTags" mode=block format=text/>
|
||||
</pre>
|
||||
|
||||
Add the following metadata:
|
||||
|
||||
```tid
|
||||
tags: $:/tags/ControlPanel/Cascades
|
||||
caption: {{$:/language/ControlPanel/ViewTemplateTags/Caption}}
|
||||
```
|
||||
|
||||
!!! Adding a New Language Entry
|
||||
|
||||
It’s important to add related language files. Create a file starting with `title: $:/language/ControlPanel/`:
|
||||
|
||||
```multid
|
||||
title: $:/language/ControlPanel/
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
!!! Adding Default Configuration
|
||||
|
||||
Similar to the language file, add a config file starting with `title: $:/config/ViewTemplateTagsFilters/`. For example:
|
||||
|
||||
```tid
|
||||
title: $:/config/ViewTemplateTagsFilters/
|
||||
tags: $:/tags/ViewTemplateTagsFilter
|
||||
|
||||
default: [[$:/core/ui/ViewTemplate/tags/default]]
|
||||
```
|
||||
|
||||
Different templates may have their own config files. Ensure you’re adding to the correct file or creating a new one if it doesn’t exist.
|
||||
|
||||
!! Using the New Cascade
|
||||
|
||||
This section provides a simplified example based on a real-world use case. It demonstrates how to override the default template with a custom template.
|
||||
|
||||
!!! Your Template
|
||||
|
||||
Add the content you want to display conditionally. Update `publisher/plugin-name` to your plugin’s name.
|
||||
|
||||
```tid
|
||||
code-body: yes
|
||||
title: $:/plugins/publisher/plugin-name/EditMode
|
||||
|
||||
\whitespace trim
|
||||
<$reveal type="nomatch" stateTitle=<<folded-state>> text="hide" tag="div" retain="yes" animate="yes">
|
||||
<div class="tc-tags-wrapper" style="display:flex">
|
||||
<$transclude tiddler="$:/core/ui/EditTemplate/tags"/>
|
||||
<$button class="tc-btn-invisible" style="margin-left:1em;">
|
||||
{{$:/core/images/done-button}}
|
||||
<$action-deletetiddler $tiddler={{{ [[$:/state/edit-view-mode-tags/]addsuffix<storyTiddler>] }}}/>
|
||||
</$button>
|
||||
</div>
|
||||
</$reveal>
|
||||
```
|
||||
|
||||
!!! The Condition
|
||||
|
||||
Write a filter that ends with `then[$:/plugins/publisher/plugin-name/EditMode]`.
|
||||
|
||||
```tid
|
||||
code-body: yes
|
||||
tags: $:/tags/ViewTemplateTagsFilter
|
||||
title: $:/plugins/publisher/plugin-name/CascadeEditMode
|
||||
list-before: $:/config/ViewTemplateTagsFilters/default
|
||||
|
||||
[[$:/state/edit-view-mode-tags/]addsuffix<currentTiddler>get[text]compare:string:eq[yes]then[$:/plugins/publisher/plugin-name/EditMode]]
|
||||
```
|
||||
|
||||
!!! A Button to Trigger the Condition
|
||||
|
||||
```tid
|
||||
code-body: yes
|
||||
tags: $:/tags/ViewTemplate/Tags
|
||||
title: $:/plugins/publisher/plugin-name/TriggerEdit
|
||||
|
||||
\whitespace trim
|
||||
<%if [<storyTiddler>get[tags]!is[blank]] %>
|
||||
<$button class="tc-btn-invisible" set={{{ [[$:/state/edit-view-mode-tags/]addsuffix<storyTiddler>] }}} setTo="yes" tooltip="add tags">
|
||||
{{$:/core/images/new-here-button}}
|
||||
</$button>
|
||||
<%endif%>
|
||||
```
|
||||
@@ -1,9 +1,10 @@
|
||||
chapter.of: UI and Rendering Pipeline
|
||||
created: 20140717175203036
|
||||
modified: 20140717182314488
|
||||
modified: 20240802065804331
|
||||
sub.num: 5
|
||||
tags: doc
|
||||
title: RootWidget and Rendering Startup
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The previous parts of this chapter showed how WikiText is transformed to DOM nodes which dynamically react to tiddler changes and a way to compose tiddlers from other tiddlers.
|
||||
This last part describes how the TiddlyWiki core plug-in starts up a UI build from tiddlers and WikiText.
|
||||
@@ -29,6 +30,9 @@ and a listener is registered at the store which executes the refresh function of
|
||||
[[Techniques for including other tiddlers and Templates|Transclusion and TextReference]] are finally used in [[$:/core/ui/PageTemplate]] to build the TiddlyWiki UI only from tiddlers written in WikiText (with widgets implemented in javascript):
|
||||
|
||||
For example to implement the list of open wiki pages the [[$:/core/ui/PageTemplate]] contains a [[navigator widget|$:/core/modules/widgets/navigator.js]] which maintains a list of open tiddlers in a field of [[$:/StoryList]] and handles events like ``tm-navigate`` by adding a tiddler specified as parameter to the top of the list in [[$:/StoryList]].
|
||||
|
||||
The [[story tiddler|$:/core/ui/PageTemplate/story]] transcluded in [[$:/core/ui/PageTemplate]] then uses a ~ListWidget to transclude all tiddlers in [[$:/StoryList]] through a special template [[$:/core/ui/ViewTemplate]].
|
||||
The ViewTemplate here is a combination of different fragments, like title fragment and body fragment, each fragment can be override individually using [[Cascade Mechanism|How to Create a Custom Cascade Entry]].
|
||||
|
||||
A event of the type ``tm-close-tiddler`` would remove a specified tiddler from [[$:/StoryList]].
|
||||
The [[Event Mechanism]] would trigger a changed event which triggers a call of the ~ListWidget's refresh function which would remove the tiddler from the list, closing the tiddler.
|
||||
|
||||
@@ -2,4 +2,4 @@ title: Using TiddlyWiki as a library in another Node.js application
|
||||
|
||||
Node.js applications can include TiddlyWiki as a library so that they can use wikitext rendering.
|
||||
|
||||
See the demo at https://github.com/TiddlyWiki/TiddlyWiki5DemoApp
|
||||
See the demo at https://github.com/Jermolene/TiddlyWiki5DemoApp
|
||||
@@ -1,5 +1,6 @@
|
||||
created: 20141115211411211
|
||||
title: ReleaseTemplate
|
||||
code-body: yes
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<h2><$link to=<<currentTab>>><$view tiddler=<<currentTab>> field="title"/></$link></h2>
|
||||
|
||||
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 826 B |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 577 B |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
@@ -1,191 +0,0 @@
|
||||
body {
|
||||
font-size: 62.5%;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #BC4378;
|
||||
}
|
||||
|
||||
.ts-loggedin .ts-openidlogin,
|
||||
.ts-loggedin .ts-login {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form input {
|
||||
width: 90px;
|
||||
border: solid 1px #CCC;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.ts-login input,
|
||||
.ts-logout input {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
form input[type=text],
|
||||
form input[type=password] {
|
||||
border-radius: 2px;
|
||||
padding: 0.1em 0.5em;
|
||||
}
|
||||
|
||||
form input[type=submit] {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.ts-logout,
|
||||
.ts-logout form {
|
||||
font-size: 1.6em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ts-logout form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#app-list {
|
||||
background: #F0F4F8;
|
||||
list-style: none;
|
||||
padding: 0; margin: 0;
|
||||
}
|
||||
|
||||
#app-list li {
|
||||
height: 4.5em;
|
||||
line-height: 4.5em;
|
||||
background: url(/bags/common/tiddlers/double_angle_lightblue_42x42.png) no-repeat 90% #F0F4F8;
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
#app-list li:hover {
|
||||
cursor: pointer;
|
||||
background: url(/bags/common/tiddlers/double_angle_lightblue_42x42.png) no-repeat 90% #0082AF;
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
#app-list li form,
|
||||
#app-list li a {
|
||||
display: block;
|
||||
height: 100%;
|
||||
font-size: 2em;
|
||||
text-decoration: none;
|
||||
color: #8C9DA7;
|
||||
width: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#app-list li input {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#app-list li:hover a {
|
||||
color: #E56AA0;
|
||||
}
|
||||
|
||||
.tsbackstage #app-list li:hover a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#app-list .app-img {
|
||||
position: relative;
|
||||
top: 0.2125em;
|
||||
margin: 0 1.25em 0 1em;
|
||||
height: 1.25em;
|
||||
width: 1.25em;
|
||||
}
|
||||
|
||||
#app-list .search .app-img {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ts-loggedin .login-method:target,
|
||||
.login-method {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login-method {
|
||||
display: block;
|
||||
}
|
||||
.login-method-hide {
|
||||
display: none;
|
||||
}
|
||||
.login-method p {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.tsbackstage .message {
|
||||
color: #4C4A54;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tsbackstage .message a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
background: #0082AF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-action:hover {
|
||||
box-shadow: 0 0 3px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
form input.btn-system {
|
||||
background: #F8F9F9;
|
||||
color: #4C4A54;
|
||||
border: 1px solid rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.btn-system:hover {
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 0 3px rgba(0,0,0,.25);
|
||||
}
|
||||
|
||||
.search form {
|
||||
height: 4.5em;
|
||||
}
|
||||
|
||||
.search input {
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0.2em 0.5em;
|
||||
background: transparent;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.search:hover input {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.search input:focus {
|
||||
-webkit-box-shadow: inset 0 0 8px rgba(140,157,167,0.75);
|
||||
-moz-box-shadow: inset 0 0 8px rgba(140,157,167,0.75);
|
||||
box-shadow: inset 0 0 8px rgba(140,157,167,0.75);
|
||||
}
|
||||
|
||||
.search:hover input:focus {
|
||||
-webkit-box-shadow: inset 0 0 8px rgba(255,255,255,0.5);
|
||||
-moz-box-shadow: inset 0 0 8px rgba(255,255,255,0.5);
|
||||
box-shadow: inset 0 0 8px rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.logindetails {
|
||||
background: #fff;
|
||||
padding: 1em 1em 2em;
|
||||
box-shadow: 0 0 6px 0px rgba(0, 0, 0, 0.25);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logindetails p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- saved from url=(0078)http://interview.tiddlyspace.com/bags/common/tiddlers/backstage#userpass-login -->
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="./normalize.css">
|
||||
<link rel="stylesheet" href="./app.css">
|
||||
</head>
|
||||
<body class="tsbackstage ts-loggedin ts-member">
|
||||
<div class="logindetails">
|
||||
<form class="ts-login login login-method" action="http://interview.tiddlyspace.com/bags/common/tiddlers/backstage" autocomplete="off" id="userpass-login">
|
||||
<p>login via <a class="toggle-form" href="http://interview.tiddlyspace.com/bags/common/tiddlers/backstage#openid-login">openid</a></p>
|
||||
<input autocapitalize="off" autocorrect="off" type="text" name="username" placeholder="username">
|
||||
<input autocapitalize="off" autocorrect="off" type="password" name="password" placeholder="password">
|
||||
<input type="hidden" name="redirect" value="/bags/common/tiddlers/backstage?action=login#refreshParent">
|
||||
<input type="submit" class="btn btn-action" value="Log In">
|
||||
</form>
|
||||
<form class="ts-openidlogin login-method login-method-hide" id="openid-login" method="post" action="http://interview.tiddlyspace.com/challenge/tiddlywebplugins.tiddlyspace.openid">
|
||||
<p>login with <a class="toggle-form" href="http://interview.tiddlyspace.com/bags/common/tiddlers/backstage#userpass-login">username and password</a></p>
|
||||
<input name="tiddlyweb_redirect" type="hidden" value="/bags/common/tiddlers/backstage">
|
||||
<input class="openid" autocapitalize="off" autocorrect="off" type="text" name="openid" placeholder="your openid">
|
||||
<input class="button btn btn-action" type="submit" value="Sign In">
|
||||
<a class="openid-help" href="http://openid.net/get-an-openid/">What is an open id?</a>
|
||||
</form>
|
||||
<div class="ts-logout logout"><span class="message">Welcome back <a href="http://jermolene.tiddlyspace.com/" target="_parent">jermolene</a><span>!</span></span>
|
||||
<form method="post" action="http://interview.tiddlyspace.com/logout">
|
||||
<input type="hidden" name="tiddlyweb_redirect" value="/bags/common/tiddlers/backstage?action=login#refreshParent">
|
||||
<input type="submit" class="btn btn-system" value="Log out">
|
||||
<input type="hidden" name="csrf_token" value="2016120917:jermolene:8cef480d1bd2bf774327ae085b2efa8bb7937fd1"></form>
|
||||
</div>
|
||||
</div>
|
||||
<div><ul id="app-list">
|
||||
<li class="search">
|
||||
<form method="GET" target="_blank" action="http://interview.tiddlyspace.com/hsearch">
|
||||
<img src="./search.png" alt="Search Icon" class="app-img">
|
||||
<input type="text" name="q" placeholder="Search">
|
||||
|
||||
</form></li>
|
||||
<li class="help">
|
||||
<a href="http://help.tiddlyspace.com/" target="_blank">
|
||||
<img src="./help.png" alt="Help SiteIcon" class="app-img">Help
|
||||
</a>
|
||||
</li>
|
||||
<li class="space">
|
||||
<a href="http://interview.tiddlyspace.com/_space" target="_blank">
|
||||
<img src="./SiteIcon(24)" alt="Space SiteIcon" class="app-img">This space
|
||||
</a>
|
||||
</li>
|
||||
<li class="account"><a target="_blank" href="http://jermolene.tiddlyspace.com/_account"><img class="app-img" alt="SiteIcon for jermolene" src="./SiteIcon">Your account</a></li></ul></div>
|
||||
<script type="text/javascript" src="./jquery.js"></script>
|
||||
<script type="text/javascript" src="./chrjs"></script>
|
||||
<script type="text/javascript" src="./chrjs.users"></script>
|
||||
<script type="text/javascript" src="./chrjs.space"></script>
|
||||
<script type="text/javascript" src="./chrjs.identities"></script>
|
||||
<script type="text/javascript" src="./ts.js"></script>
|
||||
<script src="./status.js"></script>
|
||||
<script type="text/javascript">
|
||||
if(window.location.hash === "#refreshParent") {
|
||||
window.location.hash = "";
|
||||
window.parent.location.reload();
|
||||
}
|
||||
var li, siteiconurl, link, host;
|
||||
ts.init(function(ts) {
|
||||
host = ts.getHost(ts.user.name);
|
||||
$(document.body).show();
|
||||
window.location.hash = "#userpass-login";
|
||||
if (ts.user.anon) {
|
||||
$('.toggle-form').click(function(ev) {
|
||||
$(this).closest('form').addClass('login-method-hide')
|
||||
.siblings('form').removeClass('login-method-hide');
|
||||
ev.preventDefault();
|
||||
});
|
||||
}
|
||||
if ($(document.body).hasClass('ts-nonmember')) {
|
||||
$('.write').remove();
|
||||
}
|
||||
if(!ts.user.anon) {
|
||||
li = $('<li class="account" />').appendTo("#app-list")[0];
|
||||
siteiconurl = host + '/bags/' + ts.user.name + '_public/tiddlers/SiteIcon';
|
||||
link = $('<a target="_blank" />').attr("href", host + "/_account").
|
||||
text("Your account").appendTo(li);
|
||||
$('<img class="app-img">').attr("alt", 'SiteIcon for ' + ts.user.name).
|
||||
attr("src", siteiconurl).prependTo(link);
|
||||
}
|
||||
}, {});
|
||||
(function($) {
|
||||
$(function() {
|
||||
// send doc height to parent window
|
||||
var totalHeight = $("html").height();
|
||||
if(self !== top && !!window.postMessage) {
|
||||
parent.postMessage(totalHeight, "*");
|
||||
}
|
||||
});
|
||||
}(jQuery));
|
||||
</script>
|
||||
|
||||
</body></html>
|
||||
@@ -1,360 +0,0 @@
|
||||
/***
|
||||
Adds the app switcher to a TiddlySpace app.
|
||||
|
||||
Makes use of tw.Stylesheet
|
||||
Triple licensed under the BSD, MIT and GPL licenses:
|
||||
http://www.opensource.org/licenses/bsd-license.php
|
||||
http://www.opensource.org/licenses/mit-license.php
|
||||
http://www.gnu.org/licenses/gpl.html
|
||||
***/
|
||||
(function() {
|
||||
|
||||
// Add or replace a style sheet
|
||||
// css argument is a string of CSS rule sets
|
||||
// options.id is an optional name identifying the style sheet
|
||||
// options.doc is an optional document reference
|
||||
// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.
|
||||
var twStylesheet = function(css, options) {
|
||||
options = options || {};
|
||||
var id = options.id || "backstageStyleSheet";
|
||||
var doc = options.doc || document;
|
||||
var el = doc.getElementById(id);
|
||||
if(doc.createStyleSheet) { // IE-specific handling
|
||||
if(el) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
doc.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd",
|
||||
' <style id="' + id + '" type="text/css">' + css + '</style>'); // fails without
|
||||
} else { // modern browsers
|
||||
if(el) {
|
||||
el.replaceChild(doc.createTextNode(css), el.firstChild);
|
||||
} else {
|
||||
el = doc.createElement("style");
|
||||
el.type = "text/css";
|
||||
el.id = id;
|
||||
el.appendChild(doc.createTextNode(css));
|
||||
doc.getElementsByTagName("head")[0].appendChild(el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// detect background-size support
|
||||
// in <IE9 need to fallback to msfilter property
|
||||
function hasBgSizing() {
|
||||
var supported,
|
||||
elem = document.createElement('div');
|
||||
|
||||
document.body.appendChild(elem);
|
||||
elem.style.cssText = "background-size: cover;";
|
||||
supported = (elem.style.backgroundSize === undefined || elem.style.backgroundSize === null) ? false : true;
|
||||
// clean up
|
||||
elem.parentNode.removeChild(elem);
|
||||
return supported;
|
||||
}
|
||||
|
||||
// ms filters as fix for not supporting background-size property
|
||||
var msfilter_in = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/bags/tiddlyspace/tiddlers/privateAndPublicIcon', sizingMethod='scale')",
|
||||
msfilter_out = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/bags/tiddlyspace/tiddlers/publicIcon', sizingMethod='scale')";
|
||||
|
||||
var stylesheet = ["#tsbackstage {",
|
||||
" height: 256px; /* default value unless changed */",
|
||||
" z-index: 1000;",
|
||||
" position: relative;",
|
||||
"}",
|
||||
"",
|
||||
"#app-picker {",
|
||||
" cursor: pointer;",
|
||||
" position: absolute;",
|
||||
" right: 24px;",
|
||||
" top: 0px;",
|
||||
" width: 24px;",
|
||||
" height: 24px;",
|
||||
" background-size: 24px 24px;",
|
||||
" text-indent: -999px;",
|
||||
" overflow: hidden;",
|
||||
" z-index: 2000;",
|
||||
" border: none;",
|
||||
" opacity: 0.5;",
|
||||
"}",
|
||||
"",
|
||||
"#app-picker:hover {",
|
||||
" background-color: none !important;",
|
||||
" opacity: 1;",
|
||||
"}",
|
||||
"",
|
||||
".bs-popup {",
|
||||
" width: 100%;",
|
||||
" position: absolute;",
|
||||
" z-index: 1000;",
|
||||
" right: 10px;",
|
||||
" top: 36px;",
|
||||
"}",
|
||||
"",
|
||||
".bubble .description {",
|
||||
" margin-left: 70px;",
|
||||
" margin-top: 2px;",
|
||||
"}",
|
||||
"",
|
||||
".bubble {",
|
||||
" float: right;",
|
||||
" font-size: 0.9em;",
|
||||
" font-family: Georgia;",
|
||||
" position: relative;",
|
||||
" width: 300px;",
|
||||
" margin: 0px auto 0px auto;",
|
||||
" margin: top right bottom left;",
|
||||
" border: solid 1px rgb(200, 200, 200);",
|
||||
" border-radius: 4px;",
|
||||
" -webkit-box-shadow: 0px 0px 4px rgba(0,0,0,.2);",
|
||||
" -moz-box-shadow: 0px 0px 4px rgba(0,0,0,.2);",
|
||||
" -o-box-shadow: 0px 0px 4px rgba(0,0,0,.2);",
|
||||
" -ms-box-shadow: 0px 0px 4px rgba(0,0,0,.2);",
|
||||
" box-shadow: 0px 0px 4px rgba(0,0,0,.2);",
|
||||
" background-color: #F0F4F8;",
|
||||
"}",
|
||||
"",
|
||||
".ts-logout {",
|
||||
" display: none;",
|
||||
"}",
|
||||
".ts-loggedin .ts-logout {",
|
||||
" display: block;",
|
||||
"}",
|
||||
".arrow {",
|
||||
" border-width: 0 10px 10px;",
|
||||
" border-style: dashed dashed solid;",
|
||||
" width: 0;",
|
||||
" height: 0;",
|
||||
" border-color: transparent;",
|
||||
" display: inline-block;",
|
||||
" position: absolute;",
|
||||
" top: -10px;",
|
||||
" right: 16px;",
|
||||
" border-bottom-color: #fff;",
|
||||
"}",
|
||||
".bubble div.whitearrow {",
|
||||
" top: -11px;",
|
||||
" border-bottom-color: rgba(0,0,0,0.25);",
|
||||
"}",
|
||||
".ts-terms {",
|
||||
" color: #999;",
|
||||
" display: block;",
|
||||
" font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Garuda, Verdana, Tahoma, sans-serif;",
|
||||
" font-size: 12px;",
|
||||
" font-style: normal;",
|
||||
" font-variant: normal;",
|
||||
" font-weight: normal;",
|
||||
" height: 46px;",
|
||||
" line-height: 16.7999992370605px;",
|
||||
" z-index: 800;",
|
||||
" background-color: rgb(218, 218, 218);",
|
||||
" padding-right: 50px;",
|
||||
" padding-top: 10px;",
|
||||
" padding-left: 10px;",
|
||||
" padding-bottom: 10px;",
|
||||
"}",
|
||||
".ts-terms a {",
|
||||
" color: #333;",
|
||||
"}",
|
||||
".ts-service-update {",
|
||||
" padding: 10px;",
|
||||
" background-color: red;",
|
||||
" font-family: Arial;",
|
||||
" color: #ffffff;",
|
||||
" font-size: 15px;",
|
||||
" text-align: center;",
|
||||
"}",
|
||||
".ts-service-update a {",
|
||||
" color: #ffffff;",
|
||||
" font-weight: bold;",
|
||||
" text-decoration: underline;",
|
||||
"}",
|
||||
".ts-service-update a:hover {",
|
||||
" background-color: #cc0000;",
|
||||
" text-decoration: none;",
|
||||
"}"
|
||||
].join("\n");
|
||||
|
||||
function addEventListener(node, event, handler, bubble) {
|
||||
if (node.addEventListener){
|
||||
node.addEventListener(event, handler, bubble);
|
||||
} else if (node.attachEvent){
|
||||
event = event == "click" ? "onclick" : event;
|
||||
event = event == "load" ? "onload" : event;
|
||||
node.attachEvent(event, handler);
|
||||
}
|
||||
}
|
||||
|
||||
function setCookie(cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||
var expires = "expires="+d.toUTCString();
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires;
|
||||
}
|
||||
|
||||
function getCookie(cname) {
|
||||
var name = cname + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0; i<ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1);
|
||||
if (c.indexOf(name) != -1) return c.substring(name.length,c.length);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
var loadEvent = function() {
|
||||
var link = document.createElement("a");
|
||||
link.setAttribute("id", "app-picker");
|
||||
link.setAttribute("class", "app-picker");
|
||||
link.setAttribute("title", "Click to navigate around tiddlyspace");
|
||||
link.appendChild(document.createTextNode("tiddlyspace"));
|
||||
var backgroundSizeSupported = hasBgSizing();
|
||||
|
||||
// Quite a hack. GUEST does not have a csrf token.
|
||||
if (/csrf_token=\d+:\w+:\w+/.test(document.cookie)) {
|
||||
if( backgroundSizeSupported ) {
|
||||
link.style.backgroundImage = 'url(/bags/tiddlyspace/tiddlers/privateAndPublicIcon)';
|
||||
} else {
|
||||
link.style.filter = msfilter_in;
|
||||
}
|
||||
} else {
|
||||
if( backgroundSizeSupported ) {
|
||||
link.style.backgroundImage = 'url(/bags/tiddlyspace/tiddlers/publicIcon)';
|
||||
} else {
|
||||
link.style.filter = msfilter_out;
|
||||
}
|
||||
stylesheet = stylesheet.replace('height: 180px;', 'height: 156px;');
|
||||
}
|
||||
|
||||
var body = document.getElementsByTagName("BODY")[0];
|
||||
body.insertBefore(link, body.firstChild);
|
||||
var html = [
|
||||
'<div class="bubble">',
|
||||
'<iframe src="/bags/common/tiddlers/backstage#userpass-login" name="tsbackstage" id="tsbackstage" width="auto" frameborder=0 border=0></iframe>',
|
||||
'<div class="arrow whitearrow"></div>',
|
||||
'<div class="arrow"></div>',
|
||||
'</div>'].join("");
|
||||
var bubble = document.createElement("div");
|
||||
bubble.setAttribute("id", "bs-popup");
|
||||
bubble.style.cssText = "visibility:hidden;";
|
||||
bubble.className = "bs-popup";
|
||||
bubble.innerHTML = html;
|
||||
body.insertBefore(bubble, link);
|
||||
|
||||
//Terms and Conditions
|
||||
if (document.getElementById("backstageButton")) {
|
||||
//backstage area is displayed, so also check for terms acceptance;
|
||||
var acceptedTermsVersion,
|
||||
latestTermsVersion = 'v1.0-dec2014',
|
||||
privacyPolicyOpen = false,
|
||||
cookiePolicyOpen = false;
|
||||
|
||||
acceptedTermsVersion = getCookie('termsAccepted');
|
||||
|
||||
if (acceptedTermsVersion !== latestTermsVersion) {
|
||||
html = 'The tiddlyspace service uses cookies. By using the service, you are agreeing to the <a href="http://osmo-terms.tiddlyspace.com/Cookies20141205" target="_blank">Cookie Policy</a>. We have updated tiddlyspace <a href="http://osmo-terms.tiddlyspace.com/TermsOfService20141205" target="_blank">Terms of Service</a>, effective as of 05 December 2014. By using the service you\'re agreeing to the updated terms. <a id="acceptTermsId" href="#">OK, got it</a>.';
|
||||
var terms = document.createElement('div');
|
||||
terms.setAttribute('id', 'bs-terms');
|
||||
terms.className = 'ts-terms';
|
||||
terms.innerHTML = html;
|
||||
contentWrapper = document.getElementById('contentWrapper');
|
||||
body.insertBefore(terms, contentWrapper);
|
||||
|
||||
addEventListener(document.getElementById("acceptTermsId"), "click", function(ev) {
|
||||
setCookie('termsAccepted', latestTermsVersion, 365);
|
||||
terms.style.cssText = "display:none;";
|
||||
});
|
||||
}
|
||||
|
||||
//Add Service Update Message
|
||||
html = 'Service Update: <a href="http://osmo-service.tiddlyspace.com/ServiceUpdate20161205">***Please read this important Tiddlyspace service announcement December 5th 2016 ***</a>';
|
||||
var serviceUpdate = document.createElement('div');
|
||||
serviceUpdate.setAttribute('id', 'bs-serviceUpdate');
|
||||
serviceUpdate.className = 'ts-service-update';
|
||||
serviceUpdate.innerHTML = html;
|
||||
contentWrapper = document.getElementById('contentWrapper');
|
||||
body.insertBefore(serviceUpdate, contentWrapper);
|
||||
//End of Service Update Message
|
||||
|
||||
}
|
||||
//End of Terms and Conditions
|
||||
|
||||
twStylesheet(stylesheet);
|
||||
|
||||
var bubbleFadeInterval;
|
||||
function fade(el, fadeIn) {
|
||||
var opacity = fadeIn ? 0 : 1;
|
||||
if(bubbleFadeInterval) {
|
||||
clearInterval(bubbleFadeInterval);
|
||||
}
|
||||
bubbleFadeInterval = setInterval(function() {
|
||||
// TODO: IE does not support opacity
|
||||
el.style.cssText = "opacity:" + opacity;
|
||||
opacity = fadeIn ? opacity + 0.1 : opacity - 0.1;
|
||||
if(opacity < 0 || opacity > 1) {
|
||||
clearInterval(bubbleFadeInterval);
|
||||
el.style.cssText = fadeIn ? "" : "visibility:hidden;";
|
||||
}
|
||||
}, 25);
|
||||
}
|
||||
|
||||
addEventListener(link, "mousedown", function(ev) {
|
||||
ev.preventDefault();
|
||||
}, false);
|
||||
|
||||
var bubbleOpen = false;
|
||||
var toggleBubble = function(ev) {
|
||||
if(ev.stopPropagation) {
|
||||
ev.stopPropagation();
|
||||
} else {
|
||||
ev.cancelBubble = false;
|
||||
}
|
||||
if(bubbleOpen) {
|
||||
fade(bubble, false);
|
||||
} else {
|
||||
fade(bubble, true);
|
||||
}
|
||||
bubbleOpen = !bubbleOpen;
|
||||
};
|
||||
|
||||
addEventListener(link, "click", toggleBubble);
|
||||
|
||||
addEventListener(window.document.body, "click",
|
||||
function(ev) {
|
||||
var targ,
|
||||
ev = ev || window.event;
|
||||
|
||||
if (ev.target) targ = ev.target;
|
||||
else if (ev.srcElement) targ = ev.srcElement;
|
||||
if(targ == link) {
|
||||
return;
|
||||
}
|
||||
if(bubbleOpen) {
|
||||
toggleBubble(ev);
|
||||
}
|
||||
}, true);
|
||||
|
||||
addEventListener(bubble, "click", function(ev) {
|
||||
if(ev.stopPropagation) {
|
||||
ev.stopPropagation();
|
||||
} else {
|
||||
ev.cancelBubble = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(window.top == window) { // only add the backstage when NOT in an iframe (top window)
|
||||
addEventListener(window, "load", loadEvent);
|
||||
// check if postMessage is supported
|
||||
// best test: https://github.com/ternarylabs/porthole/pull/10
|
||||
if(!!window.postMessage) {
|
||||
addEventListener(window, "message", function(e) {
|
||||
var iframe = document.getElementById('tsbackstage');
|
||||
if(e.data) {
|
||||
iframe.style.height = e.data + "px";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -1,373 +0,0 @@
|
||||
/***
|
||||
https://raw.github.com/tiddlyweb/chrjs/master/main.js
|
||||
***/
|
||||
//{{{
|
||||
// TiddlyWeb adaptor
|
||||
// v0.14.3
|
||||
|
||||
/*jslint vars: true, unparam: true, nomen: true, white: true */
|
||||
/*global jQuery */
|
||||
|
||||
var tiddlyweb = (function($) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var tw = {
|
||||
routes: {
|
||||
// host is the TiddlyWeb instance's URI (including server_prefix)
|
||||
// placeholders "_type" & "name" refer to the respective bag/recipe
|
||||
root : "{host}/",
|
||||
bags : "{host}/bags",
|
||||
bag : "{host}/bags/{name}",
|
||||
recipes : "{host}/recipes",
|
||||
recipe : "{host}/recipes/{name}",
|
||||
tiddlers : "{host}/{_type}s/{name}/tiddlers",
|
||||
tiddler : "{host}/{_type}s/{name}/tiddlers/{title}",
|
||||
revisions: "{host}/{_type}s/{name}/tiddlers/{title}/revisions",
|
||||
revision : "{host}/{_type}s/{name}/tiddlers/{title}/revisions/{revision}",
|
||||
search : "{host}/search?q={query}"
|
||||
}
|
||||
};
|
||||
|
||||
var convertTimestamp, supplant;
|
||||
|
||||
// host (optional) is the URI of the originating TiddlyWeb instance
|
||||
tw.Resource = function(type, host) {
|
||||
if(arguments.length) { // initialization
|
||||
this._type = type;
|
||||
if(host !== false) {
|
||||
this.host = host !== undefined ? host.replace(/\/$/, "") : null;
|
||||
}
|
||||
}
|
||||
};
|
||||
$.extend(tw.Resource.prototype, {
|
||||
// retrieves resource from server
|
||||
// callback is passed resource, status, XHR (cf. jQuery.ajax success)
|
||||
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
|
||||
// filters is an optional filter string (e.g. "select=tag:foo;limit=5")
|
||||
get: function(callback, errback, filters) {
|
||||
var uri = this.route();
|
||||
if(filters) {
|
||||
var separator = uri.indexOf("?") === -1 ? "?" : ";";
|
||||
uri += separator + filters;
|
||||
}
|
||||
var self = this;
|
||||
return $.ajax({
|
||||
url: uri,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(data, status, xhr) {
|
||||
var resource = self.parse(data);
|
||||
resource.etag = xhr.getResponseHeader("Etag");
|
||||
callback(resource, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
});
|
||||
},
|
||||
// sends resource to server
|
||||
// callback is passed data, status, XHR (cf. jQuery.ajax success)
|
||||
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
|
||||
put: function(callback, errback) {
|
||||
var self = this;
|
||||
var options = {
|
||||
url: this.route(),
|
||||
type: "PUT",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(this.baseData()),
|
||||
success: function(data, status, xhr) {
|
||||
callback(self, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
};
|
||||
if(this.ajaxSetup) {
|
||||
this.ajaxSetup(options);
|
||||
}
|
||||
return $.ajax(options);
|
||||
},
|
||||
// deletes resource on server
|
||||
// callback is passed data, status, XHR (cf. jQuery.ajax success)
|
||||
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
|
||||
"delete": function(callback, errback) {
|
||||
var self = this;
|
||||
var options = {
|
||||
url: this.route(),
|
||||
type: "DELETE",
|
||||
success: function(data, status, xhr) {
|
||||
callback(self, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
};
|
||||
if(this.ajaxSetup) {
|
||||
this.ajaxSetup(options);
|
||||
}
|
||||
return $.ajax(options);
|
||||
},
|
||||
// returns an object carrying only the essential information of the resource
|
||||
baseData: function() {
|
||||
var data = {},
|
||||
self = this;
|
||||
$.each(this.data, function(i, item) {
|
||||
var value = self[item];
|
||||
if(value !== undefined) {
|
||||
data[item] = value;
|
||||
}
|
||||
});
|
||||
return data;
|
||||
},
|
||||
// returns corresponding instance from a raw object (if applicable)
|
||||
parse: function(data) {
|
||||
return data;
|
||||
},
|
||||
// list of accepted keys in serialization
|
||||
data: [],
|
||||
// returns resource's URI
|
||||
route: function() {
|
||||
return supplant(tw.routes[this._type], this);
|
||||
}
|
||||
});
|
||||
|
||||
var Container = function(type, name, host) {
|
||||
if(arguments.length) { // initialization
|
||||
tw.Resource.apply(this, [type, host]);
|
||||
this.name = name;
|
||||
this.desc = "";
|
||||
this.policy = new tw.Policy({});
|
||||
}
|
||||
};
|
||||
Container.prototype = new tw.Resource();
|
||||
$.extend(Container.prototype, {
|
||||
tiddlers: function() {
|
||||
return new tw.TiddlerCollection(this);
|
||||
},
|
||||
parse: function(data) {
|
||||
var type = tw._capitalize(this._type),
|
||||
container = new tw[type](this.name, this.host);
|
||||
data.policy = new tw.Policy(data.policy);
|
||||
return $.extend(container, data);
|
||||
},
|
||||
data: ["desc", "policy"]
|
||||
});
|
||||
|
||||
// attribs is an object whose members are merged into the instance (e.g. query)
|
||||
tw.Collection = function(type, host, attribs) {
|
||||
if(arguments.length) { // initialization
|
||||
tw.Resource.apply(this, [type, host]);
|
||||
$.extend(this, attribs);
|
||||
}
|
||||
};
|
||||
tw.Collection.prototype = new tw.Resource();
|
||||
|
||||
tw.TiddlerCollection = function(container, tiddler) {
|
||||
if(arguments.length) { // initialization
|
||||
tw.Collection.apply(this, [tiddler ? "revisions" : "tiddlers"]);
|
||||
this.container = container || null;
|
||||
this.tiddler = tiddler || null;
|
||||
}
|
||||
};
|
||||
tw.TiddlerCollection.prototype = new tw.Collection();
|
||||
$.extend(tw.TiddlerCollection.prototype, {
|
||||
parse: function(data) {
|
||||
var container = this.container;
|
||||
return $.map(data, function(item, i) {
|
||||
var tiddler = new tw.Tiddler(item.title, container),
|
||||
bag = item.bag;
|
||||
tiddler = tw.Tiddler.prototype.parse.apply(tiddler, [item]);
|
||||
if(!tiddler.bag && bag) { // XXX: bag always present!?
|
||||
tiddler.bag = new tw.Bag(bag, container.host);
|
||||
}
|
||||
if(!tiddler.recipe && item.recipe) {
|
||||
tiddler.recipe = new tw.Recipe(item.recipe, container.host);
|
||||
}
|
||||
delete item.recipe;
|
||||
return $.extend(tiddler, item);
|
||||
});
|
||||
},
|
||||
route: function() {
|
||||
var params = this.container;
|
||||
if(this.tiddler) {
|
||||
var container = this.tiddler.bag || this.tiddler.recipe;
|
||||
params = {
|
||||
_type: container._type,
|
||||
host: container.host,
|
||||
name: container.name,
|
||||
title: this.tiddler.title
|
||||
};
|
||||
}
|
||||
return supplant(tw.routes[this._type], params);
|
||||
}
|
||||
});
|
||||
|
||||
tw.Search = function(query, host) {
|
||||
tw.Collection.apply(this, ["search", host]);
|
||||
this.query = query;
|
||||
};
|
||||
tw.Search.prototype = new tw.Collection();
|
||||
$.extend(tw.Search.prototype, {
|
||||
parse: function(data) {
|
||||
this.container = { // XXX: hacky
|
||||
_type: "bag",
|
||||
host: this.host
|
||||
};
|
||||
var tiddlers = tw.TiddlerCollection.prototype.parse.apply(this, arguments);
|
||||
delete this.container;
|
||||
return tiddlers;
|
||||
}
|
||||
});
|
||||
|
||||
// title is the name of the tiddler
|
||||
// container (optional) is an instance of either Bag or Recipe
|
||||
// optionally accepts a single object representing tiddler attributes
|
||||
tw.Tiddler = function(title, container) {
|
||||
tw.Resource.apply(this, ["tiddler", false]);
|
||||
this.title = title;
|
||||
this.bag = container && container._type === "bag" ? container : null;
|
||||
this.recipe = container && container._type === "recipe" ? container : null;
|
||||
var self = this;
|
||||
$.each(this.data, function(i, item) {
|
||||
self[item] = undefined; // exposes list of standard attributes for inspectability
|
||||
});
|
||||
if(title && title.title) { // title is an object of tiddler attributes
|
||||
$.extend(this, title);
|
||||
}
|
||||
};
|
||||
tw.Tiddler.prototype = new tw.Resource();
|
||||
$.extend(tw.Tiddler.prototype, {
|
||||
revisions: function() {
|
||||
return new tw.TiddlerCollection(this.bag || this.recipe, this);
|
||||
},
|
||||
route: function() {
|
||||
var container = this.bag || this.recipe;
|
||||
var params = $.extend({}, this, {
|
||||
host: container ? container.host : null,
|
||||
_type: this.bag ? "bag" : (this.recipe ? "recipe" : null),
|
||||
name: container ? container.name : null
|
||||
});
|
||||
return supplant(tw.routes[this._type], params);
|
||||
},
|
||||
parse: function(data) {
|
||||
var tiddler = new tw.Tiddler(this.title),
|
||||
container = this.bag || this.recipe;
|
||||
if(data.bag) {
|
||||
tiddler.bag = new tw.Bag(data.bag, container.host);
|
||||
delete data.bag;
|
||||
}
|
||||
delete data.recipe;
|
||||
tiddler.created = data.created ? convertTimestamp(data.created) : new Date();
|
||||
delete data.created;
|
||||
tiddler.modified = data.modified ? convertTimestamp(data.modified) : new Date();
|
||||
delete data.modified;
|
||||
if(this.recipe) {
|
||||
tiddler.recipe = this.recipe;
|
||||
}
|
||||
return $.extend(tiddler, data);
|
||||
},
|
||||
data: ["created", "creator", "modifier", "modified", "tags", "type", "text",
|
||||
"fields"],
|
||||
ajaxSetup: function(options) {
|
||||
var self = this;
|
||||
if(this.etag && (options.type === "PUT" || options.type === "DELETE")) {
|
||||
options.beforeSend = function(xhr) {
|
||||
xhr.setRequestHeader("If-Match", self.etag);
|
||||
};
|
||||
}
|
||||
if(options.type === "PUT") {
|
||||
var callback = options.success;
|
||||
options.success = function(data, status, xhr) {
|
||||
var loc = xhr.getResponseHeader("Location"),
|
||||
etag = xhr.getResponseHeader("Etag");
|
||||
if(loc && etag) {
|
||||
self.etag = etag;
|
||||
if(!self.bag) {
|
||||
var bag = loc.split("/bags/").pop().split("/")[0];
|
||||
self.bag = new tw.Bag(bag, self.recipe.host);
|
||||
}
|
||||
callback(self, status, xhr);
|
||||
} else { // IE
|
||||
self.get(callback, options.error);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tw.Revision = function(id, tiddler) {
|
||||
var container = tiddler.bag || tiddler.recipe;
|
||||
tw.Tiddler.apply(this, [tiddler.title, container]);
|
||||
this._type = "revision";
|
||||
this.revision = id;
|
||||
};
|
||||
tw.Revision.prototype = new tw.Tiddler();
|
||||
$.extend(tw.Revision.prototype, {
|
||||
revisions: false,
|
||||
data: false,
|
||||
put: false,
|
||||
"delete": false
|
||||
});
|
||||
|
||||
tw.Bag = function(name, host) {
|
||||
Container.apply(this, ["bag", name, host]);
|
||||
};
|
||||
tw.Bag.prototype = new Container();
|
||||
|
||||
tw.Recipe = function(name, host) {
|
||||
Container.apply(this, ["recipe", name, host]);
|
||||
this.recipe = [];
|
||||
};
|
||||
tw.Recipe.prototype = new Container();
|
||||
$.extend(tw.Recipe.prototype, {
|
||||
data: ["recipe"].concat(Container.prototype.data)
|
||||
});
|
||||
|
||||
tw.Policy = function(constraints) { // TODO: validation?
|
||||
var self = this;
|
||||
$.each(this.constraints, function(i, item) {
|
||||
self[item] = constraints[item];
|
||||
});
|
||||
};
|
||||
tw.Policy.prototype.constraints = ["read", "write", "create", "delete",
|
||||
"manage", "accept", "owner"];
|
||||
|
||||
/*
|
||||
* utilities
|
||||
*/
|
||||
|
||||
tw._capitalize = function(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
// convert YYYYMMDDhhmmss timestamp to Date instance
|
||||
convertTimestamp = function(t) {
|
||||
if (t.match(/^\d{12,17}$/)) {
|
||||
return new Date(Date.UTC(
|
||||
parseInt(t.substr(0, 4), 10),
|
||||
parseInt(t.substr(4, 2), 10) - 1,
|
||||
parseInt(t.substr(6, 2), 10),
|
||||
parseInt(t.substr(8, 2), 10),
|
||||
parseInt(t.substr(10, 2), 10),
|
||||
parseInt(t.substr(12, 2) || "0", 10),
|
||||
parseInt(t.substr(14, 3) || "0", 10)
|
||||
));
|
||||
} else {
|
||||
return new Date(Date.parse(t));
|
||||
}
|
||||
};
|
||||
|
||||
// adapted from Crockford (http://javascript.crockford.com/remedial.html)
|
||||
supplant = function(str, obj) {
|
||||
return str.replace(/{([^{}]*)}/g, function (a, b) {
|
||||
var r = obj[b];
|
||||
r = typeof r === "string" || typeof r === "number" ? r : a;
|
||||
return $.inArray(b, ["host", "query"]) !== -1 ? r : encodeURIComponent(r); // XXX: special-casing
|
||||
});
|
||||
};
|
||||
|
||||
return tw;
|
||||
|
||||
}(jQuery));
|
||||
//}}}
|
||||
@@ -1,42 +0,0 @@
|
||||
/***
|
||||
TiddlySpace extensions for [[chrjs]]
|
||||
|''Requires''|chrjs.users|
|
||||
***/
|
||||
//{{{
|
||||
(function($) {
|
||||
|
||||
tiddlyweb.routes.identities = "{host}/users/{username}/identities";
|
||||
var IdentitiesCollection = function(user) {
|
||||
tiddlyweb.Collection.apply(this, ["identities", user.host, {
|
||||
username: user.username
|
||||
}]);
|
||||
};
|
||||
IdentitiesCollection.prototype = new tiddlyweb.Collection();
|
||||
jQuery.extend(IdentitiesCollection.prototype, {
|
||||
add: function(identity, callback, errback) {
|
||||
var tiddler = new tiddlyweb.Tiddler(identity);
|
||||
tiddler.bag = new tiddlyweb.Bag("MAPUSER", this.host);
|
||||
tiddler.put(callback, errback);
|
||||
},
|
||||
get: function(callback, errback) {
|
||||
var uri = this.route();
|
||||
$.ajax({
|
||||
type: "get",
|
||||
dataType: "json",
|
||||
url: uri,
|
||||
success: function(uris, status, xhr) {
|
||||
callback(uris, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
tiddlyweb.User.prototype.identities = function() {
|
||||
return new IdentitiesCollection(this);
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
//}}}
|
||||
@@ -1,108 +0,0 @@
|
||||
/***
|
||||
TiddlySpace extensions for [[chrjs]]
|
||||
***/
|
||||
//{{{
|
||||
(function($) {
|
||||
|
||||
tiddlyweb.routes.spaces = "{host}/spaces";
|
||||
tiddlyweb.routes.space = "{host}/spaces/{name}";
|
||||
tiddlyweb.routes.members = "{host}/spaces/{name}/members";
|
||||
tiddlyweb.routes.member = "{host}/spaces/{name}/members/{username}";
|
||||
|
||||
tiddlyweb.Space = function(name, host) {
|
||||
tiddlyweb.Resource.apply(this, ["space", host]);
|
||||
this.name = name;
|
||||
};
|
||||
tiddlyweb.Space.prototype = new tiddlyweb.Resource();
|
||||
$.extend(tiddlyweb.Space.prototype, {
|
||||
create: function(callback, errback) { // API wrapper
|
||||
this.put.apply(this, arguments);
|
||||
},
|
||||
members: function() {
|
||||
return new MemberCollection(this);
|
||||
},
|
||||
includes: function() {
|
||||
return new IncludesCollection(this);
|
||||
}
|
||||
});
|
||||
|
||||
var Member = function(username, space) {
|
||||
tiddlyweb.Resource.apply(this, ["member", space.host]);
|
||||
this.name = space.name;
|
||||
this.username = username;
|
||||
};
|
||||
Member.prototype = new tiddlyweb.Resource();
|
||||
|
||||
var MemberCollection = function(space) {
|
||||
tiddlyweb.Collection.apply(this, ["members", space.host, {
|
||||
name: space.name
|
||||
}]);
|
||||
};
|
||||
MemberCollection.prototype = new tiddlyweb.Collection();
|
||||
$.extend(MemberCollection.prototype, {
|
||||
add: function(username, callback, errback) {
|
||||
var member = new Member(username, this);
|
||||
member.put(callback, errback);
|
||||
},
|
||||
remove: function(username, callback, errback) {
|
||||
var member = new Member(username, this);
|
||||
member["delete"](callback, errback);
|
||||
}
|
||||
});
|
||||
|
||||
var IncludesCollection = function(space) {
|
||||
tiddlyweb.Collection.apply(this, ["space", space.host, {
|
||||
name: space.name
|
||||
}]);
|
||||
};
|
||||
IncludesCollection.prototype = new tiddlyweb.Collection();
|
||||
$.extend(IncludesCollection.prototype, {
|
||||
get: function(callback, errback) {
|
||||
var self = this;
|
||||
var recipe = new tiddlyweb.Recipe(this.name + "_public", this.host);
|
||||
recipe.get(function(recipe, status, xhr) {
|
||||
var inclusions = $.map(recipe.recipe, function(item, i) {
|
||||
var arr = item[0].split("_public");
|
||||
return (arr[0] != self.name && arr[1] === "") ? arr[0] : null;
|
||||
});
|
||||
callback(inclusions, status, xhr);
|
||||
}, function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
});
|
||||
},
|
||||
add: function(name, callback, errback) {
|
||||
var self = this;
|
||||
var names = typeof(name) === "string" ? [ name ] : name;
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: this.route(),
|
||||
contentType: "json",
|
||||
data: JSON.stringify({ "subscriptions": names }),
|
||||
success: function(response, status, xhr) {
|
||||
callback(self, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
});
|
||||
},
|
||||
remove: function(name, callback, errback) {
|
||||
var self = this;
|
||||
var names = typeof(name) === "string" ? [ name ] : name;
|
||||
$.ajax({
|
||||
type: "post",
|
||||
contentType: "json",
|
||||
url: this.route(),
|
||||
data: JSON.stringify({ "unsubscriptions": names }),
|
||||
success: function(response, status, xhr) {
|
||||
callback(self, status, xhr);
|
||||
},
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
//}}}
|
||||
@@ -1,57 +0,0 @@
|
||||
/***
|
||||
https://raw.github.com/tiddlyweb/chrjs/master/users.js
|
||||
***/
|
||||
//{{{
|
||||
// chrjs users extension
|
||||
// v0.5.0
|
||||
//
|
||||
// requires tiddlywebplugins.socialusers
|
||||
// http://pypi.python.org/pypi/tiddlywebplugins.socialusers
|
||||
|
||||
/*jslint vars: true */
|
||||
/*global jQuery, tiddlyweb */
|
||||
|
||||
(function($, tw) {
|
||||
|
||||
"use strict";
|
||||
|
||||
tw.routes.users = "{host}/users";
|
||||
tw.routes.user = "{host}/users/{username}";
|
||||
|
||||
tw.User = function(username, password, host) {
|
||||
tw.Resource.apply(this, ["user", host]);
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
};
|
||||
tw.User.prototype = new tw.Resource();
|
||||
$.extend(tw.User.prototype, {
|
||||
create: function(callback, errback) {
|
||||
var uri = this.route().split("/"); // XXX: hacky!?
|
||||
uri.pop();
|
||||
uri = uri.join("/");
|
||||
var data = {
|
||||
username: this.username,
|
||||
password: this.password
|
||||
};
|
||||
var self = this;
|
||||
return $.ajax({
|
||||
url: uri,
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(data),
|
||||
success: callback,
|
||||
error: function(xhr, error, exc) {
|
||||
errback(xhr, error, exc, self);
|
||||
}
|
||||
});
|
||||
},
|
||||
setPassword: function(newPass, callback, errback) {
|
||||
this.old_password = this.password; // XXX: should not use underscore (consistency)
|
||||
this.password = newPass;
|
||||
return this.put(callback, errback);
|
||||
},
|
||||
data: ["password", "old_password"]
|
||||
});
|
||||
|
||||
}(jQuery, tiddlyweb));
|
||||
//}}}
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,406 +0,0 @@
|
||||
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
|
||||
|
||||
/* ==========================================================================
|
||||
HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct `inline-block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9.
|
||||
* Hide the `template` element in IE, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `outline` inconsistency between Chrome and other browsers.
|
||||
*/
|
||||
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Typography
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct font family set oddly in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability of pre-formatted text in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set consistent quote types.
|
||||
*/
|
||||
|
||||
q {
|
||||
quotes: "\201C" "\201D" "\2018" "\2019";
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow displayed oddly in IE 9.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari 5.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct font family not being inherited in all browsers.
|
||||
* 2. Correct font size not being inherited in all browsers.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
|
||||
* Correct `select` style inheritance in Firefox 4+ and Opera.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari 5 and Chrome
|
||||
* on OS X.
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove default vertical scrollbar in IE 8/9.
|
||||
* 2. Improve readability and alignment in all browsers.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto; /* 1 */
|
||||
vertical-align: top; /* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
@@ -1,2 +0,0 @@
|
||||
var tiddlyweb = tiddlyweb || {};
|
||||
tiddlyweb.status = {"username": "jermolene", "tiddlyspace_version": "1.2.26", "space": {"recipe": "interview_private", "name": "interview"}, "challengers": ["tiddlywebplugins.tiddlyspace.cookie_form", "tiddlywebplugins.tiddlyspace.openid"], "server_host": {"host": "tiddlyspace.com", "scheme": "http", "port": "80"}, "version": "1.4.18"};
|
||||
@@ -1,766 +0,0 @@
|
||||
/***
|
||||
https://raw.github.com/TiddlySpace/ts.js/master/src/ts.js
|
||||
***/
|
||||
//{{{
|
||||
/*jslint vars: true, browser: true */
|
||||
/*global jQuery, tiddlyweb, confirm, prompt */
|
||||
//
|
||||
// version 0.5.12
|
||||
(function($) {
|
||||
"use strict";
|
||||
|
||||
var getCSRFToken = function() {
|
||||
// XXX: should not use RegEx - cf.
|
||||
// http://www.quirksmode.org/js/cookies.html
|
||||
// https://github.com/TiddlySpace/tiddlyspace/commit/5f4adbe009ed4bda3ce39058a3fb07de1420358d
|
||||
var regex = /^(?:.*; )?csrf_token=([^(;|$)]*)(?:;|$)/;
|
||||
var match = regex.exec(document.cookie);
|
||||
var csrf_token = null;
|
||||
if (match && (match.length === 2)) {
|
||||
csrf_token = match[1];
|
||||
}
|
||||
|
||||
return csrf_token;
|
||||
};
|
||||
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader("X-ControlView", "false");
|
||||
}
|
||||
});
|
||||
|
||||
window.getCSRFToken = getCSRFToken;
|
||||
|
||||
/*
|
||||
* Add the members of spaceName to the current space.
|
||||
*/
|
||||
function addMembersfromSpace(ts, spaceName, callback, errback) {
|
||||
new tiddlyweb.Space(spaceName, "/").members().get(function(members) {
|
||||
var spaceMembers = new tiddlyweb.Space(ts.currentSpace, "/").
|
||||
members(),
|
||||
putMembers = function(members, callback, errback) {
|
||||
var currentMember = members.shift();
|
||||
if (currentMember) {
|
||||
var next = function() {
|
||||
putMembers(members, callback, errback);
|
||||
};
|
||||
spaceMembers.add(currentMember, next, errback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
putMembers(members, callback, errback);
|
||||
}, errback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the message area associated with the provided form.
|
||||
*/
|
||||
function resetMessage(form) {
|
||||
$(".annotation", form).removeClass("annotation");
|
||||
$(".messageArea", form).removeClass("error").hide();
|
||||
$(".inputArea", form).show();
|
||||
}
|
||||
|
||||
/*
|
||||
* Build message area element
|
||||
*/
|
||||
function buildMsgArea(form) {
|
||||
var msgArea = $("<div class='messageArea' />");
|
||||
msgArea
|
||||
.append($("<button></button>")
|
||||
.html("×")
|
||||
.addClass("close-btn")
|
||||
.attr("title", "close notification")
|
||||
.data("parent-class", "messageArea")
|
||||
.click( function() {
|
||||
resetMessage(form);
|
||||
return false;
|
||||
} )
|
||||
)
|
||||
.append( $("<p></p>") );
|
||||
|
||||
var container = $("<div />").appendTo(msgArea)[0];
|
||||
$("<a />").text("Try again?").click(function() {
|
||||
$("input", form)[0].focus();
|
||||
}).appendTo(container);
|
||||
|
||||
return msgArea;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a message aligned with the provided form.
|
||||
*/
|
||||
function displayMessage(form, msg, error, options) {
|
||||
options = options || {};
|
||||
if(options.hideForm) {
|
||||
$(".inputArea", form).hide();
|
||||
} else {
|
||||
$(".inputArea", form).show();
|
||||
}
|
||||
var msgArea = $(".messageArea", form);
|
||||
if(msgArea.length === 0) {
|
||||
msgArea = buildMsgArea(form);
|
||||
msgArea.prependTo(form);
|
||||
}
|
||||
|
||||
// replace error msg
|
||||
msgArea
|
||||
.find("p")
|
||||
.empty()
|
||||
.html(msg || ts.locale.error)
|
||||
.end()
|
||||
.show(100);
|
||||
|
||||
var errorDiv = msgArea.find("div");
|
||||
if(error) {
|
||||
msgArea.addClass("error annotation");
|
||||
errorDiv.show();
|
||||
} else {
|
||||
msgArea.removeClass("error");
|
||||
errorDiv.hide();
|
||||
}
|
||||
if(options.annotate) {
|
||||
$(options.annotate, form).addClass("annotation");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the default initialization behaviors.
|
||||
*/
|
||||
function defaultInit(ts, status, callback, options) {
|
||||
options = options || {};
|
||||
if (status.space && status.space.name &&
|
||||
typeof options.space === "undefined") {
|
||||
options.space = status.space.name;
|
||||
}
|
||||
ts.resolveCurrentSpaceName(options, status.server_host.host);
|
||||
if(!ts.currentSpace) {
|
||||
$(document.body).addClass("ts-unknown-space");
|
||||
}
|
||||
ts.loadStatus(status);
|
||||
if(status.identity || ts.parameters.openid) {
|
||||
ts.register_openid(status.identity);
|
||||
} else if(status.username && ts.parameters.openid) {
|
||||
// open id login occurred so redirect to homespace
|
||||
window.location.href = ts.parameters.redirect ||
|
||||
ts.getHost(status.username);
|
||||
}
|
||||
// do login status
|
||||
ts.forms.password($("form.ts-password")[0]);
|
||||
ts.loginStatus();
|
||||
if(ts.currentSpace) {
|
||||
ts.initForSpace(status);
|
||||
}
|
||||
if(callback) {
|
||||
callback(ts);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse query parameters into a simple object.
|
||||
*/
|
||||
function parseParameters(queryString) {
|
||||
var args = queryString.split(/[&;]/),
|
||||
parameters = {},
|
||||
i,
|
||||
nameval;
|
||||
for(i = 0; i < args.length; i += 1) {
|
||||
nameval = args[i].split("=");
|
||||
if(nameval.length === 2) {
|
||||
parameters[nameval[0]] = nameval[1];
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/*
|
||||
* add CSRF form fields to the provided form.
|
||||
*/
|
||||
function addCSRF(form) {
|
||||
$("<input type='hidden' name='csrf_token' />").
|
||||
val(getCSRFToken()).appendTo(form);
|
||||
}
|
||||
|
||||
var ts = {
|
||||
currentSpace: false,
|
||||
locale: {
|
||||
error: "An error occurred",
|
||||
tryAgain: "Please try again",
|
||||
success: "Clear this notification",
|
||||
badLogin: "We are unable to log you in with those details.",
|
||||
charError: "Username is invalid - must only contain lowercase " +
|
||||
"letters, digits or hyphens",
|
||||
spaceSuccess: "Successfully created space.",
|
||||
userError: "Username is already taken, please choose another.",
|
||||
passwordError: "Passwords do not match",
|
||||
passwordLengthError: "Error: password must be at least 6 characters",
|
||||
invalidSpaceError: ["error: invalid space name - must start with a ",
|
||||
"letter, be at least two characters in length and only contain ",
|
||||
"lowercase letters, digits or hyphens"].join("")
|
||||
},
|
||||
status: {},
|
||||
user: {},
|
||||
resolveCurrentSpaceName: function(options, host) {
|
||||
if(options && typeof options.space !== "undefined") {
|
||||
ts.currentSpace = options.space;
|
||||
} else if(window.location.protocol !== "file:") {
|
||||
var hostname = window.location.hostname;
|
||||
if(host.split(".").length < hostname.split(".").length) {
|
||||
ts.currentSpace = hostname.split(".")[0];
|
||||
}
|
||||
}
|
||||
},
|
||||
isValidSpaceName: function(name) {
|
||||
return name.match(/^[a-z][0-9a-z\-]*[0-9a-z]$/) ? true : false;
|
||||
},
|
||||
init: function(callback, options) {
|
||||
ts.parameters = parseParameters(window.location.search.substr(1));
|
||||
var status = tiddlyweb.status;
|
||||
if (status) {
|
||||
defaultInit(ts, status, callback, options);
|
||||
}
|
||||
},
|
||||
initForSpace: function(status) {
|
||||
if (/_private$/.test(status.space.recipe)) {
|
||||
$(document.body).addClass("ts-member");
|
||||
ts.forms.addInclude($("form.ts-includes")[0]);
|
||||
ts.forms.addMember($("form.ts-members")[0]);
|
||||
ts.forms.addSpace($("form.ts-spaces")[0]);
|
||||
} else {
|
||||
$(document.body).addClass("ts-nonmember");
|
||||
}
|
||||
ts.initLists();
|
||||
},
|
||||
getSpaces: function(callback) {
|
||||
if(ts.spaces) {
|
||||
callback(ts.spaces);
|
||||
} else {
|
||||
$.ajax({
|
||||
url: "/spaces?mine=1",
|
||||
dataType: "json",
|
||||
success: function(spaces) {
|
||||
ts.spaces = spaces;
|
||||
callback(ts.spaces);
|
||||
},
|
||||
error: function() {
|
||||
ts.spaces = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
initLists: function() {
|
||||
ts.lists.identities();
|
||||
ts.lists.members();
|
||||
ts.lists.includes();
|
||||
},
|
||||
loadStatus: function(status) {
|
||||
ts.status = status;
|
||||
ts.user = {
|
||||
name: status.username,
|
||||
anon: status.username ? status.username === "GUEST" : true
|
||||
};
|
||||
},
|
||||
getHost: function(subdomain) {
|
||||
var s = ts.status;
|
||||
var host = s.server_host;
|
||||
subdomain = subdomain ? subdomain + "." : "";
|
||||
var url = host.scheme + "://" + subdomain + host.host;
|
||||
var port = host.port;
|
||||
if(port && port !== "80" && port !== "443") {
|
||||
url += ":" + port;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
login: function(username, password, options) {
|
||||
options = options || {};
|
||||
var success = options.success || function() {
|
||||
window.location = options.redirect || ts.getHost(username);
|
||||
};
|
||||
// XXX void errback?
|
||||
var errback = options.errback || function() {};
|
||||
var challenger = options.challenger = options.challenger ||
|
||||
"/challenge/tiddlywebplugins.tiddlyspace.cookie_form";
|
||||
$.ajax({
|
||||
url: challenger,
|
||||
type: "POST",
|
||||
data: {
|
||||
user: username,
|
||||
password: password,
|
||||
csrf_token: getCSRFToken(),
|
||||
// workaround to marginalize automatic subsequent GET
|
||||
tiddlyweb_redirect: "/status"
|
||||
},
|
||||
success: success,
|
||||
error: errback
|
||||
});
|
||||
},
|
||||
parameters: {},
|
||||
register_openid_for_user: function(username, openid) {
|
||||
var user = new tiddlyweb.User(username, null, "/");
|
||||
user.identities().add(openid, function() {
|
||||
window.location.href = window.location.pathname;
|
||||
}, function() {
|
||||
throw "failed to add identity to current user.";
|
||||
});
|
||||
},
|
||||
register_openid: function(openid) {
|
||||
var space = ts.parameters.space;
|
||||
var username = ts.parameters.user;
|
||||
if(!space && !username) {
|
||||
var answer = confirm(
|
||||
"Would you like to create a space with your openid: " +
|
||||
openid + "?"
|
||||
);
|
||||
if(answer) {
|
||||
space = prompt("What would you like to be your TiddlySpace username?");
|
||||
}
|
||||
}
|
||||
if(space && openid) {
|
||||
var possible =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var password = "";
|
||||
while(password.length < 16) {
|
||||
password += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
// register user with username of space and random password
|
||||
ts.register(space, password, null, {
|
||||
errback: function() {
|
||||
throw "failed at step 1/3";
|
||||
},
|
||||
success: function() {
|
||||
// login as that newly created user
|
||||
ts.login(space, password, {
|
||||
success: function() {
|
||||
ts.register_openid_for_user(space, openid);
|
||||
},
|
||||
errback: function() {
|
||||
throw "failed at step 2/3";
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if(username) {
|
||||
ts.register_openid_for_user(username, ts.parameters.openid);
|
||||
}
|
||||
},
|
||||
register: function(username, password, form, options) {
|
||||
options = options || {};
|
||||
var spaceCallback = options.success || function() {
|
||||
displayMessage(form, ts.locale.spaceSuccess, false);
|
||||
window.location = options.redirect || ts.getHost(username);
|
||||
};
|
||||
var spaceErrback = function (xhr) {
|
||||
// XXX: 409 unlikely to occur at this point
|
||||
var msg = xhr.status === 409 ? ts.locale.userError : false;
|
||||
displayMessage(form, msg, true, options);
|
||||
};
|
||||
var userCallback = function() {
|
||||
ts.login(username, password, {
|
||||
success: function() {
|
||||
var space = new tiddlyweb.Space(username, "/");
|
||||
space.create(spaceCallback, spaceErrback);
|
||||
}
|
||||
});
|
||||
};
|
||||
var userErrback = function(xhr) {
|
||||
var msg = xhr.status === 409 ? ts.locale.userError : false;
|
||||
displayMessage(form, msg, true, options);
|
||||
};
|
||||
var user = new tiddlyweb.User(username, password, "/");
|
||||
user.create(userCallback, userErrback);
|
||||
},
|
||||
createSpace: function(form, spaceName, callback, errback) {
|
||||
if(ts.isValidSpaceName(spaceName)) {
|
||||
var space = new tiddlyweb.Space(spaceName, "/");
|
||||
space.create(callback, errback);
|
||||
} else {
|
||||
displayMessage(form, ts.locale.invalidSpaceError, true);
|
||||
}
|
||||
},
|
||||
changePassword: function(username, password, npassword, form) {
|
||||
var pwCallback = function() {
|
||||
var msg = "Successfully changed your password.";
|
||||
displayMessage(form, msg);
|
||||
};
|
||||
var pwErrback = function() {
|
||||
var msg = "Old password is incorrect.";
|
||||
displayMessage(form, msg, true);
|
||||
};
|
||||
var user = new tiddlyweb.User(username, password, "/");
|
||||
user.setPassword(npassword, pwCallback, pwErrback);
|
||||
},
|
||||
loginStatus: function() {
|
||||
var register = $("form.ts-registration");
|
||||
var login = $("form.ts-login");
|
||||
var logout = $(".ts-logout");
|
||||
|
||||
var user = ts.user;
|
||||
$("form.ts-openid").each(function(i, el) {
|
||||
ts.forms.openid(el, { user: user });
|
||||
});
|
||||
if(!user.anon) {
|
||||
$(document.body).addClass("ts-loggedin");
|
||||
$([register, login]).remove();
|
||||
logout.each(function(i, el) {
|
||||
ts.forms.logout(el);
|
||||
});
|
||||
} else {
|
||||
if(register) {
|
||||
ts.forms.register(register);
|
||||
}
|
||||
if(login) {
|
||||
ts.forms.login(login);
|
||||
}
|
||||
logout.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
ts.forms = {
|
||||
password: function(form) {
|
||||
$(form).submit(function(ev) {
|
||||
ev.preventDefault();
|
||||
var oldPass = $("[name=password]").val();
|
||||
var newPass = $("[name=new_password]").val();
|
||||
var newPass2 = $("[name=new_password_confirm]").val();
|
||||
if(newPass !== newPass2) {
|
||||
var msg = "Passwords do not match";
|
||||
displayMessage(form, msg, true);
|
||||
} else if(newPass.length < 6) {
|
||||
displayMessage(form, ts.locale.passwordLengthError, true);
|
||||
} else {
|
||||
ts.changePassword(ts.user.name, oldPass, newPass, form);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
addInclude: function(form) {
|
||||
if(!form) {
|
||||
return;
|
||||
}
|
||||
addCSRF(form);
|
||||
$(form).submit(function(ev) {
|
||||
ev.preventDefault();
|
||||
var input = $("input[name=spacename]", form);
|
||||
var space = input.val();
|
||||
var callback = function() {
|
||||
ts.lists.includes($("ul.ts-includes").empty()[0]);
|
||||
input.val("");
|
||||
var msg = space + " included";
|
||||
displayMessage(form, msg, false);
|
||||
};
|
||||
var errback = function() {
|
||||
var msg = "Unable to include space with that name.";
|
||||
displayMessage(form, msg, true);
|
||||
};
|
||||
new tiddlyweb.Space(ts.currentSpace, "/").includes().
|
||||
add(space, callback, errback);
|
||||
});
|
||||
},
|
||||
addMember: function(form) {
|
||||
if(!form) {
|
||||
return;
|
||||
}
|
||||
addCSRF(form);
|
||||
$(form).submit(function(ev) {
|
||||
ev.preventDefault();
|
||||
var input = $("input[name=username]", form);
|
||||
var username = input.val();
|
||||
var spaceName = /^@/.test(username) ? username.slice(1) :
|
||||
null;
|
||||
var callback = function() {
|
||||
ts.lists.members($("ul.ts-members").empty()[0]);
|
||||
input.val("");
|
||||
resetMessage(form);
|
||||
};
|
||||
var errback = function(xhr) {
|
||||
if(xhr.status === 403) {
|
||||
displayMessage(form,
|
||||
"Unable to add members from a space you " +
|
||||
"are not a member of",
|
||||
true);
|
||||
} else if (xhr.status === 409) {
|
||||
displayMessage(form,
|
||||
"Unknown username entered.",
|
||||
true);
|
||||
} else {
|
||||
var msg = "Unknown error occurred.";
|
||||
displayMessage(form, msg, true);
|
||||
}
|
||||
};
|
||||
if (!spaceName) {
|
||||
new tiddlyweb.Space(ts.currentSpace, "/").members().
|
||||
add(username, callback, errback);
|
||||
} else {
|
||||
addMembersfromSpace(ts, spaceName, callback, errback);
|
||||
}
|
||||
});
|
||||
},
|
||||
addSpace: function(form) {
|
||||
if(!form) {
|
||||
return;
|
||||
}
|
||||
var selector = "[name=spacename]";
|
||||
addCSRF(form);
|
||||
$(form).submit(function(ev) {
|
||||
ev.preventDefault();
|
||||
var spaceName = $(selector, form).val() || "";
|
||||
var callback = function() {
|
||||
var host = ts.getHost(spaceName),
|
||||
msg = "Successfully created <a href='" +
|
||||
host + "'>" + host + "</a>.";
|
||||
displayMessage(form, msg, false);
|
||||
};
|
||||
var errback = function() {
|
||||
var msg = "Problem creating a space with that name.";
|
||||
displayMessage(form, msg, true);
|
||||
};
|
||||
ts.createSpace(form, spaceName, callback, errback);
|
||||
});
|
||||
},
|
||||
register: function(form, options) {
|
||||
options = options || {};
|
||||
addCSRF(form);
|
||||
$(form).submit(function(ev) {
|
||||
ev.preventDefault();
|
||||
var username = $("[name=username]", form).val();
|
||||
var password = $("[name=password]", form).val();
|
||||
options.redirect = $("[name=redirect]", form).val();
|
||||
var passwordConfirm = $("[name=password_confirm]",
|
||||
form).val();
|
||||
var validName = ts.isValidSpaceName(username);
|
||||
var validLength = password.length >= 6;
|
||||
if(validName && validLength && password &&
|
||||
password === passwordConfirm) {
|
||||
ts.register(username, password, ev.target, options);
|
||||
} else {
|
||||
var msg = validName ?
|
||||
(!validLength ? ts.locale.passwordLengthError :
|
||||
ts.locale.passwordError) :
|
||||
ts.locale.charError;
|
||||
options.annotate = validName ? "[type=password]" :
|
||||
"[name=username]";
|
||||
displayMessage(form, msg, true, options);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
openid: function(form, options) {
|
||||
addCSRF(form);
|
||||
$(form).attr("method", "post").
|
||||
attr("action",
|
||||
"/challenge/tiddlywebplugins.tiddlyspace.openid").
|
||||
submit(function(ev) {
|
||||
var identity = $("input[name=openid]", form).val(),
|
||||
space = $("input[name=space]", form).val(),
|
||||
user = options && options.user ?
|
||||
options.user.name : null;
|
||||
if(!identity) {
|
||||
ev.preventDefault();
|
||||
return displayMessage(form,
|
||||
"Please provide an openid!");
|
||||
}
|
||||
var querystring = "?openid=" + identity;
|
||||
if(space) {
|
||||
querystring += "&space=" + space;
|
||||
}
|
||||
if(user) {
|
||||
querystring += "&user=" + user;
|
||||
}
|
||||
var redirect = $("[name=redirect]", form).val();
|
||||
if(redirect) {
|
||||
querystring += "&redirect=" + redirect;
|
||||
}
|
||||
// IMPORTANT: #auth:OpenID=<openid> is read by the openid tiddlyweb plugin
|
||||
// when present it keeps you logged in as your cookie username
|
||||
$("<input name='tiddlyweb_redirect' type='hidden' />").
|
||||
val(window.location.pathname + querystring +
|
||||
"#auth:OpenID=" + identity).appendTo(form);
|
||||
});
|
||||
},
|
||||
logout: function(form_or_container) {
|
||||
if(!form_or_container) {
|
||||
return;
|
||||
}
|
||||
var tag = form_or_container.nodeName;
|
||||
var form;
|
||||
var isContainer = tag !== "FORM";
|
||||
if(isContainer) {
|
||||
var uri = ts.getHost(ts.user.name);
|
||||
var link = $("<a />").attr({"href": uri,
|
||||
"target": "_parent"}).text(ts.user.name)[0];
|
||||
var msg = $("<span class='message' />").
|
||||
text("Welcome back ").prependTo(form_or_container)[0];
|
||||
$(msg).append(link);
|
||||
$("<span />").text("!").appendTo(msg);
|
||||
form = $("form", form_or_container)[0];
|
||||
if(!form) {
|
||||
form = $("<form />").appendTo(form_or_container)[0];
|
||||
$("<input type='submit' class='button' value='Log out'>").appendTo(form);
|
||||
}
|
||||
} else {
|
||||
form = form_or_container;
|
||||
}
|
||||
$(form).attr("action", "/logout").attr("method", "post");
|
||||
addCSRF(form);
|
||||
},
|
||||
login: function(form) {
|
||||
// do login
|
||||
addCSRF(form);
|
||||
var options = {
|
||||
errback: function(xhr) {
|
||||
var code = xhr.status;
|
||||
if(code === 401) {
|
||||
displayMessage(form, ts.locale.badlogin, true);
|
||||
} else {
|
||||
displayMessage(form, ts.locale.tryAgain, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
function doLogin(ev) {
|
||||
var user = $("input[name=username]", form).val();
|
||||
var pass = $("input[name=password]", form).val();
|
||||
if(!user) {
|
||||
return displayMessage(form, "Please provide a username!");
|
||||
}
|
||||
if(!pass) {
|
||||
return displayMessage(form, "Please provide a password!");
|
||||
}
|
||||
options.redirect = $("input[name=redirect]", form).val();
|
||||
options.challenger = $(form).attr("action");
|
||||
ts.login(user, pass, options);
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
$(form).submit(function(ev) {
|
||||
doLogin(ev);
|
||||
});
|
||||
|
||||
$(form).keypress(function(ev) {
|
||||
if(ev.keyCode === 13) {
|
||||
doLogin(ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
ts.lists = {
|
||||
identities: function() {
|
||||
var list = $("ul.ts-identities")[0];
|
||||
if (list) {
|
||||
$(list).addClass("ts-loading");
|
||||
var user = new tiddlyweb.User(ts.user.name, null, "/");
|
||||
user.identities().get(
|
||||
function(identities) {
|
||||
var i;
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
for(i = 0; i < identities.length; i += 1) {
|
||||
$("<li />").text(identities[i]).appendTo(list);
|
||||
}
|
||||
},
|
||||
function() {
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
includes: function() {
|
||||
var space = new tiddlyweb.Space(ts.currentSpace, "/");
|
||||
var removeInclusion = function(ev) {
|
||||
var item = $(ev.target).parents("li")[0];
|
||||
var target_space = $(ev.target).data("inclusion");
|
||||
var callback = function() {
|
||||
$(item).hide(200);
|
||||
};
|
||||
var errback = function() {};
|
||||
space.includes().remove(target_space, callback, errback);
|
||||
};
|
||||
var list = $("ul.ts-includes").addClass("ts-loading")[0];
|
||||
if(list) {
|
||||
var callback = function(inclusions) {
|
||||
var i, item;
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
for(i = 0; i < inclusions.length; i += 1) {
|
||||
item = $("<li />").appendTo(list)[0];
|
||||
$("<a />")
|
||||
.text(inclusions[i])
|
||||
.attr("href", ts.getHost(inclusions[i]))
|
||||
.attr("title", "visit icluded space")
|
||||
.appendTo(item);
|
||||
addDeleteBtn("inclusion", inclusions[i], item, removeInclusion);
|
||||
}
|
||||
};
|
||||
var errback = function(xhr) {
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
$("<li class='annotation' />").
|
||||
text("Error requesting inclusions:" + xhr.status + " " + xhr.statusText).
|
||||
prependTo(list);
|
||||
};
|
||||
space.includes().get(callback, errback);
|
||||
}
|
||||
},
|
||||
members: function() {
|
||||
var space = new tiddlyweb.Space(ts.currentSpace, "/");
|
||||
var removeMember = function(ev) {
|
||||
var list = $(ev).parents("ul.members")[0];
|
||||
var item = $(ev.target).parents("li")[0];
|
||||
var member = $(ev.target).data("member");
|
||||
var callback = function() {
|
||||
$(item).hide(200, function() {
|
||||
$(item).remove();
|
||||
if($("ul.ts-members li:visible").length > 1) {
|
||||
$("button.delete", list).show();
|
||||
}
|
||||
});
|
||||
$("button.delete", list).hide();
|
||||
};
|
||||
var errback = function() {
|
||||
// Um ought to be something here
|
||||
};
|
||||
space.members().remove(member, callback, errback);
|
||||
};
|
||||
var list = $("ul.ts-members").addClass("ts-loading")[0];
|
||||
if(list) {
|
||||
var callback = function(members) {
|
||||
var i, item;
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
members = members.sort();
|
||||
for(i = 0; i < members.length; i += 1) {
|
||||
item = $("<li />").appendTo(list)[0];
|
||||
$("<a />")
|
||||
.text(members[i])
|
||||
.attr("href", ts.getHost(members[i]))
|
||||
.attr("title", "visit member's home space")
|
||||
.appendTo(item);
|
||||
if(members.length > 1) {
|
||||
addDeleteBtn("member", members[i], item, removeMember);
|
||||
}
|
||||
}
|
||||
};
|
||||
var errback = function() {
|
||||
$(list).removeClass("ts-loading").empty();
|
||||
$("<li class='annotation' />").
|
||||
text("Only members can see other members.").
|
||||
prependTo(list);
|
||||
};
|
||||
space.members().get(callback, errback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function addDeleteBtn(type, data, item, cb) {
|
||||
$("<button />")
|
||||
.addClass("delete")
|
||||
.data(type, data)
|
||||
.attr("title", "remove " + type)
|
||||
.html("×")
|
||||
.click(cb)
|
||||
.appendTo(item);
|
||||
}
|
||||
|
||||
ts.parseParameters = parseParameters;
|
||||
window.ts = {
|
||||
init: ts.init
|
||||
};
|
||||
|
||||
}(jQuery));
|
||||
//}}}
|
||||
@@ -1,3 +0,0 @@
|
||||
This folder contains the output of using "save HTML file" in the browser viewing the interview project on TiddlySpace. This is not a TiddlyWiki; it is a snapshot of the HTML generated by an instance of TiddlyWiki.
|
||||
|
||||
See the `./scripts` directory for the tools used to extract the data from this file.
|
||||
@@ -0,0 +1,13 @@
|
||||
created: 20251021142729667
|
||||
modified: 20251021142729667
|
||||
tags:
|
||||
title: Concatenating a text reference to create a URL
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! Concatenating variables and a text reference to create a URL
|
||||
|
||||
<$macrocall $name=wikitext-example src="""<$let hash={{{ [<currentTiddler>encodeuricomponent[]] }}}>
|
||||
<a href=`${ [{!!base-url}] }$#$(hash)$`>this tiddler on tiddlywiki.com</a>
|
||||
</$let>"""/>
|
||||
|
||||
See: [[Substituted Attribute Values]]
|
||||
@@ -0,0 +1,13 @@
|
||||
created: 20251021142733998
|
||||
modified: 20251021142733998
|
||||
tags:
|
||||
title: Concatenating variables to create a URL
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! Concatenating strings and variables to create a URL
|
||||
|
||||
<$macrocall $name=wikitext-example src="""<$let hash={{{ [<currentTiddler>encodeuricomponent[]] }}}>
|
||||
<a href=`http://tiddlywiki.com/#$(hash)$`>this tiddler on tiddlywiki.com</a>
|
||||
</$let>"""/>
|
||||
|
||||
See: [[Substituted Attribute Values]]
|
||||
13
editions/tw5.com/tiddlers/Deprecated Core Classes.tid
Normal file
@@ -0,0 +1,13 @@
|
||||
created: 20251015120940754
|
||||
modified: 20251101092833913
|
||||
tags: $:/deprecated [[Core Classes]]
|
||||
title: Deprecated Core Classes
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.warning "It is not recommended to use these classes for styling. Though tiddlywiki might still support them, they may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using them, and update existing code if possible. Be aware that this feature may cease to work at any time.">>
|
||||
|
||||
These [[Core Classes]] are considered deprecated. It is not recommend to use them for styling.
|
||||
|
||||
* `tc-tagged-*` <<.deprecated-since 5.1.16>> Use [[Custom styles by data-tags]] instead.
|
||||
* `tc-reveal` <<.deprecated-since 5.3.8>> for styling purposes as it is subject to change.
|
||||
* `tc-language-(language code)` <<.deprecated-since 5.3.8>> Please use [[:lang()|https://developer.mozilla.org/en-US/docs/Web/CSS/:lang]] instead.
|
||||
@@ -1,11 +1,10 @@
|
||||
created: 20240313100515958
|
||||
modified: 20240313103959789
|
||||
modified: 20251023154747366
|
||||
tags: Editions
|
||||
title: TiddlyWiki Docs PR Maker
|
||||
|
||||
''~TiddlyWiki Docs PR Maker'' is a special edition of tiddlywiki.com designed to help you contribute to and improve the documentation made by [[@saqimtiaz|https://github.com/saqimtiaz/]].
|
||||
|
||||
https://saqimtiaz.github.io/tw5-docs-pr-maker/
|
||||
''~TiddlyWiki Docs PR Maker'' is a special edition of tiddlywiki.com designed to help you contribute to and improve the documentation.
|
||||
https://edit.tiddlywiki.com
|
||||
|
||||
All changes made to the documentation can be very easily submitted to GitHub -- the pull request will be automatically made, hence the "PR Maker" name of the edition.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150412191004348
|
||||
modified: 20240925114810504
|
||||
modified: 20251022153208584
|
||||
tags: Community Reference
|
||||
title: Developers
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -8,3 +8,4 @@ type: text/vnd.tiddlywiki
|
||||
* Get involved in the [[development on GitHub|https://github.com/TiddlyWiki/TiddlyWiki5]]
|
||||
* [[GitHub Discussions|https://github.com/TiddlyWiki/TiddlyWiki5/discussions]] are for Q&A and open-ended discussion
|
||||
* [[GitHub Issues|https://github.com/TiddlyWiki/TiddlyWiki5/issues]] are for raising bug reports and proposing specific, actionable new ideas
|
||||
* See [[Contributing]] for guidelines on how to contribute to the project.
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
title: Filter Syntax History
|
||||
tags: [[History of TiddlyWiki]]
|
||||
modifier: Jeremy Ruston
|
||||
created: 20250730154331065
|
||||
modified: 20250730154331065
|
||||
modified: 20250731162557775
|
||||
modifier: Jeremy Ruston
|
||||
tags: [[History of TiddlyWiki]]
|
||||
title: Filter Syntax History
|
||||
|
||||
In response to [[a discussion|https://talk.tiddlywiki.org/t/filter-syntax-history/13058]] about the filter syntax in TiddlyWiki5 I posted this brief personal history.
|
||||
|
||||
For context, before TiddlyWiki, I only had practical experience of a very small number of languages: machine code, assembly language, BASIC, FORTH, C, C++ and of course JavaScript. I had a smattering of Java, Pascal and one or two other ancient languages but no experience of actor based languages like Erlang, or modern functional languages.
|
||||
|
||||
The story starts with the double square bracket syntax used in wikitext for links. In 2004 this was already an established usage in wikis. However, I switched the ordering of pretty links because I thought Wikipedia's `[[link address|link text]]` was the wrong way around. It broke up sentences: `The file is [[https://site.com/thing|here]]` seems less readable than `The file is [[here|https://site.com/thing]]`. For a long time I regretted this decision, and wished that I had just gone with Wikipedia's established usage. Others have since pointed out that TiddlyWiki's ordering is actually consistent with [[Markdown]], which might be regarded as the winner of the markup wars.
|
||||
The story starts with the double square bracket syntax used in wikitext for links. In 2004 this was already an established usage in wikis. However, I switched the ordering of pretty links because I thought Wikipedia's `[[link address|link text]]` was the wrong way around. It broke up sentences: `The file is [[https://site.com/thing|here]]` seems less readable than `The file is [[here|https://site.com/thing]]`. For a long time I regretted this decision, and wished that I had just gone with Wikipedia's established usage. Others have since pointed out that ~TiddlyWiki's ordering is actually consistent with [[Markdown]], which might be regarded as the winner of the markup wars.
|
||||
|
||||
I looked at the double square bracket link syntax is that it establishes a way to quote page/tiddler titles so that they may contain spaces, and don't have to use CamelCase. Thus, right at the start of TiddlyWiki Classic when I was implementing the first iteration of the DefaultTiddlers feature it was natural to use double square brackets to quote titles containing spaces, making a list of titles to be opened at startup.
|
||||
I looked at the double square bracket link syntax is that it establishes a way to quote page/tiddler titles so that they may contain spaces, and don't have to use CamelCase. Thus, right at the start of [[TiddlyWiki Classic|TiddlyWikiClassic]] when I was implementing the first iteration of the DefaultTiddlers feature it was natural to use double square brackets to quote titles containing spaces, making a list of titles to be opened at startup.
|
||||
|
||||
Soon, I wanted to extend the implementation of DefaultTiddlers so that it could be used to open all tiddlers with a particular tag while retaining backwards compatibility.
|
||||
|
||||
A trick that I am apt to use in such situations is to try to engineer things so that the current behaviour is re-interpreted as a shortcut syntax for a new, richer syntax that provides more flexibility. In this case, the idea was that in filters we would interpret `[[mytiddler]]` as a shortcut for `[title[mytiddler]]`. Then we could put any keywords we like in place of "title", giving us an infinitely extensible syntax. A similar example is the way that we implemented filter run prefixes by retrospectively defining the absence of a prefix as implying a default prefix.
|
||||
|
||||
The new syntax was first [introduced in 2007] (see [this commit](https://github.com/TiddlyWiki/TiddlyWikiClassic/commit/1928962ea6811b1ca67378ed3cd62059a9806ae9)), with a simplified syntax that only supported a single `tag` operator but was just about sufficient for intended purpose. The only documentation was a comment in the source code (complete with a typo):
|
||||
The new syntax was first [[introduced in 2007|https://github.com/TiddlyWiki/TiddlyWikiClassic/commit/1928962ea6811b1ca67378ed3cd62059a9806ae9]], with a simplified syntax that only supported a single `tag` operator but was just about sufficient for intended purpose. The only documentation was a comment in the source code (complete with a typo):
|
||||
|
||||
```
|
||||
// Filter a list of tiddlers
|
||||
@@ -24,19 +24,19 @@ The new syntax was first [introduced in 2007] (see [this commit](https://github.
|
||||
//# Returns an array of Tiddler() objects that match the filter expression
|
||||
```
|
||||
|
||||
Provision to combine the filter operators had been on my mind from the beginning. When TiddlyWiki 5 started in 2011 I reused the simple implementation from TiddlyWiki Classic. Smashing operators [was finally implemented in May 2012](https://github.com/TiddlyWiki/TiddlyWiki5/commit/8b0703b694e982b2bc448bdb133742164723dd8a). By the time of the launch the filter language had grown into pretty much what it is today -- see the [documentation for TiddlyWiki v5.1.0](https://tiddlywiki.com/archive/full/TiddlyWiki-5.1.0#Introduction%20to%20Filters).
|
||||
Provision to combine the filter operators had been on my mind from the beginning. When ~TiddlyWiki 5 started in 2011 I reused the simple implementation from ~TiddlyWiki Classic. Smashing operators [[was finally implemented in May 2012|https://github.com/TiddlyWiki/TiddlyWiki5/commit/8b0703b694e982b2bc448bdb133742164723dd8a]]. By the time of the launch the filter language had grown into pretty much what it is today -- see the [[documentation for TiddlyWiki v5.1.0|https://tiddlywiki.com/archive/full/TiddlyWiki-5.1.0#Introduction%20to%20Filters]].
|
||||
|
||||
The filter syntax had undoubtedly evolved into something approaching a programming language. As others have probably expressed much more eloquently, a characteristic of the programming languages that I love is that they start with a small number of principles that are consistently applied and combined. In the case of TiddlyWiki, the list would be very roughly:
|
||||
The filter syntax had undoubtedly evolved into something approaching a programming language. As others have probably expressed much more eloquently, a characteristic of the programming languages that I love is that they start with a small number of principles that are consistently applied and combined. In the case of ~TiddlyWiki, the list would be very roughly:
|
||||
|
||||
* Double square brackets for linking and quoting
|
||||
* Curly braces for transclusion
|
||||
* Angle brackets for macros (which evolved into variables)
|
||||
* Double square brackets for [[linking and quoting|Linking in WikiText]]
|
||||
* Curly braces for [[transclusion|Transclusion in WikiText]]
|
||||
* Angle brackets for [[macros|Procedures]] (which evolved into variables)
|
||||
* Double exclamation marks to indicate fields `{{!!myfield}}`
|
||||
* Double hashes to indicate indexes `{{##myindex}}`
|
||||
* Smashing together adjacent filter operations by removing the combining `][`
|
||||
* The dollar sign as a rough signifier of data owned by the system rather than the user
|
||||
* Smashing together adjacent [[filter operations|Introduction to filter notation]] by removing the combining `][`
|
||||
* The dollar sign as a rough signifier of data [[owned by the system|Transclusion in WikiText]] rather than the user
|
||||
|
||||
As I have written about elsewhere I was privileged to know Joe Armstrong, the co-inventor of Erlang, in the last few years of his life – we were working together on a book about TiddlyWiki when he passed away in 2019. Joe had contacted me out of the blue ten years before to express his admiration for TiddlyWiki, and we had developed a friendship. He was actually a big fan of TW5's filter syntax, and used to make me feel better about it by joking that I had (re-)invented the monad, which sounded impressive to me. That doesn't make the filter language any easier to learn, but it does mean that it is *worth* learning: it's a real language, based on the same principles as other languages.
|
||||
As I have written about elsewhere I was privileged to know Joe Armstrong, the co-inventor of Erlang, in the last few years of his life – we were working together on a book about ~TiddlyWiki when he passed away in 2019. Joe had contacted me out of the blue ten years before to express his admiration for ~TiddlyWiki, and we had developed a friendship. He was actually a big fan of TW5's filter syntax, and used to make me feel better about it by joking that I had (re-)invented the monad, which sounded impressive to me. That doesn't make the filter language any easier to learn, but it does mean that it is *worth* learning: it's a real language, based on the same principles as other languages.
|
||||
|
||||
I find it pleasing that the TW5 filter language has its roots in decisions that were taken in the TWC days. It's still hard to learn, but that's an ongoing paradox of programming: people want to do complicated things, and complicated things are complicated. It's hard to see how we could have made filters any simpler without depriving users of the possibility of doing complicated things.
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
created: 20140908114400000
|
||||
modified: 20250730154331065
|
||||
modified: 20251122174540932
|
||||
tags: About
|
||||
title: History of TiddlyWiki
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Gathering the history of ~TiddlyWiki. This is an ongoing project. Contributions and reminiscences are welcome.
|
||||
|
||||
Here is a brief history of TiddlyWiki, its origins and its evolution since it was first released on 20th September 2004. Contributions and reminiscences are welcome.
|
||||
|
||||
* [[The Story of TiddlyWiki]] – a personal account of the story of TiddlyWiki, its origins and evolution
|
||||
* [[TiddlyWiki Anniversaries]] – relive the celebrations of TiddlyWiki's major anniversaries
|
||||
* [[Filter Syntax History]] – gives a brief history of the evolution of the filter syntax in TiddlyWiki5
|
||||
* [[The Story of TiddlyWiki]] – A personal account from [[@Jermolene]] of the story of TiddlyWiki, its origins and evolution
|
||||
* https://github.com/TiddlyWiki/LaunchArchive – Blog posts and tweets from TiddlyWiki's launch in 2004
|
||||
* [[TiddlyWiki Anniversaries]] – Relive the celebrations of TiddlyWiki's major anniversaries
|
||||
* [[Filter Syntax History]] – A brief history of the evolution of the filter syntax in TiddlyWiki5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: render
|
||||
created: 20170919131752774
|
||||
modified: 20170919131805871
|
||||
modified: 20250811164528905
|
||||
tags: Commands
|
||||
title: RenderCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -10,6 +10,7 @@ type: text/vnd.tiddlywiki
|
||||
<$button class="tc-btn-invisible" style="text-decoration:underline">
|
||||
Show available rendering templates
|
||||
<$action-setfield $tiddler="$:/temp/advancedsearch" text="[all[shadows]prefix[$:/core/templates/]]"/>
|
||||
<$action-setfield $tiddler="$:/temp/advancedsearch/input" text="[all[shadows]prefix[$:/core/templates/]]"/>
|
||||
<$action-setfield $tiddler="$:/state/tab--1498284803" text="$:/core/ui/AdvancedSearch/Filter"/>
|
||||
<$action-navigate $to="$:/AdvancedSearch"/>
|
||||
</$button>
|
||||
|
||||
@@ -3,7 +3,7 @@ created: 20250708130030654
|
||||
modified: 20250826162904085
|
||||
|
||||
<div style.float="right" style.padding-left="1em">
|
||||
<$image source="Community Survey 2025.png" alt="Shaping the future of TiddlyWiki with the Community Survey 2025" width="280"/>
|
||||
<$image source="Community Survey 2025" alt="Shaping the future of TiddlyWiki with the Community Survey 2025" width="280"/>
|
||||
</div>
|
||||
|
||||
The core developers work hard year by year to continuously improve ~TiddlyWiki. Part of the satisfaction is that we are not just building software for ourselves, we’re serving the needs of a wider community of users.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20140820151051019
|
||||
modified: 20240313114828368
|
||||
modified: 20251023154718268
|
||||
tags: Community
|
||||
title: Improving TiddlyWiki Documentation
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -20,7 +20,7 @@ You can choose to edit the documentation using the [[TiddlyWiki Docs PR Maker]]
|
||||
|
||||
!! Using [[Docs PR Maker|TiddlyWiki Docs PR Maker]] edition
|
||||
|
||||
# Go to https://saqimtiaz.github.io/tw5-docs-pr-maker/ or click the link displayed in the ribbon underneath the title when editing a tiddler on tiddlywiki.com
|
||||
# Go to https://edit.tiddlywiki.com or click the link displayed in the ribbon underneath the title when editing a tiddler on tiddlywiki.com
|
||||
# Go through the quick introduction where you will need to provide your ~GitHub username and a ~GitHub access token (you will be guided in creating one)
|
||||
# Edit or create tiddlers to update the documentation, the wiki will keep track of all changes
|
||||
# Click the "Submit updates" button and check if all the tiddlers that you edited are included in the submission; if not, drag them into the box
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
created: 20160204225047445
|
||||
lost-url: http://www.networkworld.com/article/3028098/open-source-tools/tiddlywiki-a-free-open-source-wiki-revisited.html
|
||||
modified: 20160204225307847
|
||||
tags: Articles
|
||||
title: "A free, open source wiki revisited" by Mark Gibbs, NetworkWorld
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://www.networkworld.com/article/3028098/open-source-tools/tiddlywiki-a-free-open-source-wiki-revisited.html
|
||||
url: https://web.archive.org/web/20180911094717/https://www.networkworld.com/article/3028098/open-source-tools/tiddlywiki-a-free-open-source-wiki-revisited.html
|
||||
|
||||
Interesting article giving the perspective of someone who has been away from TiddlyWiki for a few years:
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
created: 20141122093837330
|
||||
lost-url: http://cardo.wiki
|
||||
modified: 20210106151026996
|
||||
tags: [[Community Editions]]
|
||||
title: "Cardo - Task and Project Management Wiki" by David Szego
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://cardo.wiki
|
||||
url: https://web.archive.org/web/20181114094516/http://cardo.wiki/#Joe%20Cardo:%5B%5BJoe%20Cardo%5D%5D
|
||||
|
||||
Task & Delegation Tracking, Meetings & Agenda Items, Project Roles, Progress & Status Updates, Reference Items, Tickler Calendar, Conversation Logging, Book Notes & Library, and More!
|
||||
|
||||
@@ -11,4 +12,10 @@ Task & Delegation Tracking, Meetings & Agenda Items, Project Roles, Progress & S
|
||||
|
||||
<<<
|
||||
Cardo is a standalone, browser-based tool that can be used as a simple task manager, or as a complex Project Management system (and indeed, I do use it this way in my daily work) as well as a fully Wiki-ized personal knowledge store. It runs completely independently in the browser, even without an Internet connection, making it possible to carry around on a USB stick, or to use on the morning commute.
|
||||
<<<
|
||||
<<<
|
||||
|
||||
|
||||
* https://cardo-revisited.tiddlyhost.com (re-activated TW v5.3.8)
|
||||
* https://cardo-dyumnin.tiddlyhost.com (TW v5.1.19)
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ modified: 20140716084548184
|
||||
tags: Examples
|
||||
title: "PETTIL - Forth for the Commodore PET" by Charlie Hitselberger
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://pettilmobile.com/tw/
|
||||
url: http://pettilmobile.com
|
||||
|
||||
A fast Forth interpreter for the [[Commodore PET|https://en.wikipedia.org/wiki/Commodore_PET]], written in 6502 assembly language. The TiddlyWiki containing program documentation is automatically generated from the source code: see https://github.com/chitselb/pettil.
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
created: 20141122093837330
|
||||
lost-url: http://luckysushi.ru/habarovsk/heeg.html
|
||||
modified: 20210106151027143
|
||||
tags: Examples
|
||||
title: "Lucky Sushi" online shop by sini-Kit
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://luckysushi.ru/habarovsk/heeg.html#index
|
||||
url: https://web.archive.org/web/20241127033249/http://luckysushi.ru/habarovsk/heeg.html#index
|
||||
|
||||
A complete online shop made in ~TiddlyWiki!
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
created: 20150403110356105
|
||||
lost-url: http://tw5-dev.cibm.de
|
||||
modified: 20210106151027470
|
||||
tags: [[Community Plugins]]
|
||||
title: IndexedDB Plugin by Andreas Abeck
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://tw5-dev.cibm.de
|
||||
url: https://web.archive.org/web/20180118083556/http://tw5-dev.cibm.de/
|
||||
|
||||
A plugin that allows changes to be synchronised with the IndexedDB database that is built-in to most browsers.
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
created: 20201117162655614
|
||||
modified: 20201117162926714
|
||||
modified: 20251020041616967
|
||||
tags: [[Community Plugins]]
|
||||
title: Slider by Mohammad
|
||||
type: text/vnd.tiddlywiki
|
||||
url: https://kookma.github.io/slider/
|
||||
url: https://kookma.github.io/TW-Slider/
|
||||
|
||||
Slider is a plugin to create an ordered set of tiddlers also called Trail.
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
created: 20251009192405351
|
||||
modified: 20251009192405351
|
||||
tags: [[Community Plugins]] Resources
|
||||
title: TW5-Graph by Flibbles
|
||||
type: text/vnd.tiddlywiki
|
||||
url: https://flibbles.github.io/tw5-graph/
|
||||
|
||||
TW5-Graph is a framework to integrate TiddlyWiki with existing graphing and visualization engines (such as [[Vis-Network|https://visjs.github.io/vis-network/docs/network/]]). The plugin allows for easy and sophisticated graphs to represent your tiddlers, or whatever else you want.
|
||||
|
||||
It is the spiritual successor to [[TiddlyMap|TiddlyMap Plugin by Felix Küppers]].
|
||||
|
||||
With TW5-Graph you can:
|
||||
|
||||
* Quickly create and edit graphs through a simple point-and-click GUI
|
||||
* Use wikitext widgets to create customized graphs and template to exactly match your needs
|
||||
* Easily create dynamic graphs to represent changing state or individual tiddlers
|
||||
|
||||
There's loads TW5-Graph can do for you. [[Check out its demo website here.|https://flibbles.github.io/tw5-graph/]]
|
||||
|
||||
Or visit its source code [[here|https://github.com/flibbles/tw5-graph]].
|
||||
@@ -1,16 +0,0 @@
|
||||
created: 20140410103123179
|
||||
modified: 20210106151027370
|
||||
tags: [[Other Resources]]
|
||||
title: "TWeb.at" by Mario Pietsch
|
||||
type: text/vnd.tiddlywiki
|
||||
url: https://tweb.at
|
||||
|
||||
A collection of TiddlyWiki resources from Mario Pietsch, with a focus on cloud deployments. Mario also maintains the German translation of TiddlyWiki.
|
||||
|
||||
{{!!url}}
|
||||
|
||||
<<<
|
||||
My name is Mario Pietsch from Austria. I'm living near Salzburg.
|
||||
|
||||
This page, will be the portal to my TiddlyWiki, TiddlyWeb related content.
|
||||
<<<
|
||||
@@ -1,9 +1,10 @@
|
||||
created: 20140716085406905
|
||||
lost-url: http://bibliobox.net/blog/post/2014/07/16/un-wiki-sur-votre-bibliobox-avec-tiddlywiki
|
||||
modified: 20140716084548184
|
||||
tags: Tutorials
|
||||
title: "Un wiki sur votre BiblioBox avec TiddlyWiki" from A Penguin in Redmond
|
||||
type: text/vnd.tiddlywiki
|
||||
url: http://bibliobox.net/blog/post/2014/07/16/un-wiki-sur-votre-bibliobox-avec-tiddlywiki
|
||||
url: https://web.archive.org/web/20210305133610/http://bibliobox.net/blog/post/2014/07/16/un-wiki-sur-votre-bibliobox-avec-tiddlywiki
|
||||
|
||||
A guide (in French) to using TiddlyWiki on the [[BiblioBox|http://bibliobox.net/]], a variation of the [[PirateBox|http://daviddarts.com/piratebox/]] mobile communication and file sharing system.
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{
|
||||
"path": "../../../../community",
|
||||
"isTiddlerFile": true,
|
||||
"isEditableFile": true,
|
||||
"filesRegExp": "^(?!readme\\.md$)(?!\\.DS_Store$).+",
|
||||
"searchSubdirectories": true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20240507221902644
|
||||
modified: 20240729082610287
|
||||
modified: 20250814073256942
|
||||
tags: Concepts
|
||||
title: CompoundTiddlers
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -8,7 +8,7 @@ Compound tiddlers are a special type of tiddler that can store one or more paylo
|
||||
|
||||
The compound tiddler format is extremely simple, and includes the notable flaw that it does not permit tiddlers that contain a plus sign (`+`) on a line by itself. It is not intended as a general purpose way of storing tiddler data.
|
||||
|
||||
Compound tiddlers are identified by having their type field set to `text/vnd.tiddlywiki-multiple`.
|
||||
Compound tiddlers are identified by having their [[type field|ContentType]] set to `text/vnd.tiddlywiki-multiple`.
|
||||
|
||||
The content of a compound tiddler consists of a sequence of tiddlers separated by a plus sign (`+`) on a line by itself. Each tiddler uses the same format as [[.tid files|TiddlerFiles]].
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ type: text/vnd.tiddlywiki
|
||||
There are two ways default tiddlers can be defined:
|
||||
|
||||
* A [[title-list|Title List]] eg: `TiddlerTitle` and `[[Title with spaces]]`
|
||||
* [[Filter expressions|Filter Expression], using filter operators eg: `[tag[HelloThere]]`
|
||||
* [[Filter expressions|Filter Expression]], using filter operators eg: `[tag[HelloThere]]`
|
||||
|
||||
The resulting list of titles is then inserted into the [[story river|Story River]].
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20130828185900000
|
||||
modified: 20150221120839000
|
||||
modified: 20250814073940003
|
||||
tags: Definitions
|
||||
title: ContentType
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -11,19 +11,20 @@ In TiddlyWiki, the `type` field gives the content type to apply to the main `tex
|
||||
!! List of Common Content Types
|
||||
|
||||
|!Group |!Type |!Content of `type` field |
|
||||
|^''Developer'' |Data dictionary |application/x-tiddler-dictionary|
|
||||
|~|~JavaScript code |application/javascript|
|
||||
|~|JSON data |application/json|
|
||||
|~|Static stylesheet |text/css|
|
||||
|^''Developer'' |[[Data dictionary|DictionaryTiddlers]] |application/x-tiddler-dictionary|
|
||||
|~|[[Compound Tiddler|CompoundTiddlers]] |text/vnd.tiddlywiki-multiple|
|
||||
|~|JavaScript code |application/javascript|
|
||||
|~|[[JSON data|JSONTiddlers]] |application/json|
|
||||
|~|[[Static stylesheet|Using Stylesheets]] |text/css|
|
||||
|^''Image''|GIF image |image/gif|
|
||||
|~|ICO format icon file |image/x-icon|
|
||||
|~|JPEG image |image/jpeg|
|
||||
|~|PDF image |application/pdf|
|
||||
|~|PNG image |image/png|
|
||||
|~|Structured Vector Graphics image |image/svg+xml|
|
||||
|^''Text''|HTML markup |text/html|
|
||||
|^''Text''|[[HTML markup|HyperText Markup Language]] |text/html|
|
||||
|~|[[CSS|Cascading Style Sheets]] stylesheet |text/css|
|
||||
|~|[[Comma-separated values|Comma-Separated Values]] |text/csv|
|
||||
|~|Plain text |text/plain|
|
||||
|~|~TiddlyWiki 5 |text/vnd.tiddlywiki|
|
||||
|~|~TiddlyWiki Classic |text/x-tiddlywiki|
|
||||
|~|[[TiddlyWiki 5|WikiText]] |text/vnd.tiddlywiki|
|
||||
|~|[[TiddlyWiki Classic|TiddlyWikiClassic]] |text/x-tiddlywiki|
|
||||
|
||||
@@ -4,22 +4,22 @@ tags: Learning
|
||||
title: TaskManagementExample
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TiddlyWiki5 can be used as a simple task management system without further customisation. The idea is that tasks be tagged `task`, with those that are completed also tagged `done`. In this way it is straightforward to generate task lists.
|
||||
TiddlyWiki5 can be used as a simple task management system without further customisation.<br>The idea is that tasks be tagged `task`, with those that are completed also tagged `done`. In this way it is straightforward to generate task lists.
|
||||
|
||||
<<.tip """There is [[an enhanced version of this demo|TaskManagementExample (Draggable)]] that adds the ability to drag and drop the tasks to re-order them.""">>
|
||||
|
||||
! Outstanding tasks
|
||||
|
||||
<$list filter="[!has[draft.of]tag[task]!tag[done]sort[created]]">
|
||||
|
||||
<$checkbox tag="done"> <$link/></$checkbox>
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""<$list filter="[!has[draft.of]tag[task]!tag[done]sort[created]]">
|
||||
<$checkbox tag="done"> <$link/></$checkbox><br>
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
! Completed tasks
|
||||
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
|
||||
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox><br>
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
@@ -4,20 +4,24 @@ tags: Learning
|
||||
title: TaskManagementExample (Draggable)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This is a version of the TaskManagementExample enhanced with the ability to drag and drop the task list to re-order them.
|
||||
This is a version of the TaskManagementExample enhanced with the ability to drag and drop the task list to re-order them.<br>The list uses a the itemTemplate [[TaskManagementExampleDraggableTemplate]] tiddler, which you will also need to experiment yourself.
|
||||
|
||||
! Outstanding tasks
|
||||
|
||||
//Drag the tasks to re-order them//
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""//Drag the tasks to re-order them//
|
||||
|
||||
<<list-tagged-draggable tag:"task" subFilter:"!has[draft.of]!tag[done]" itemTemplate:"TaskManagementExampleDraggableTemplate" emptyMessage:"You don't have any active tasks">>
|
||||
"""/>
|
||||
|
||||
! Completed tasks
|
||||
|
||||
//(Listed in reverse order of completion)//
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""//(Listed in reverse order of completion)//
|
||||
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[modified]]">
|
||||
<div>
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
|
||||
</div>
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
@@ -1,37 +1,60 @@
|
||||
created: 20230614225302905
|
||||
modified: 20230614233448662
|
||||
modified: 20251021140446753
|
||||
tags: [[Operator Examples]] [[substitute Operator]]
|
||||
title: substitute Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define time() morning
|
||||
\define field() modified
|
||||
!! Substitute operator parameters
|
||||
|
||||
The following example uses a ''function definition'' and a ''function call'' with a ''filter expression''
|
||||
|
||||
<<wikitext-example-without-html """\function f.text() [[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]]
|
||||
|
||||
<<f.text>>
|
||||
""">>
|
||||
|
||||
---
|
||||
|
||||
The following example uses a [[filtered transclusion|Transclusion in WikiText]] with a [[filter expression|Filter Syntax]] creating a link and a text output.
|
||||
|
||||
<<wikitext-example-without-html """link: {{{ [[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]] }}}
|
||||
|
||||
text: <$text text={{{ [[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]] }}}/>
|
||||
""">>
|
||||
|
||||
|
||||
!! Substitute variables and parameters
|
||||
|
||||
The following example uses [[variable definitions|Pragma: \procedure]] "name", "address", a ''filtered transclusion'' assigned to a ''text-widget''. The variables "name" and "address" are used as ''substitute parameters''.
|
||||
|
||||
<<wikitext-example-without-html """\procedure name() Bugs Bunny
|
||||
\procedure address() Rabbit Hole Hill
|
||||
|
||||
<$text text={{{ [[Hi, I'm $1$ and I live in $2$]substitute<name>,<address>] }}}/>
|
||||
""">>
|
||||
|
||||
!! Substitute $(variables)$
|
||||
|
||||
The following examples use the variables "name" and "address" and directly substitute the with the [[attribute substitution|Substituted Attribute Values]] syntax.
|
||||
|
||||
<<wikitext-example-without-html """\procedure name() Bugs Bunny
|
||||
\procedure address() Rabbit Hole Hill
|
||||
|
||||
<$text text=`Hi, I'm $(name)$ and I live in $(address)$`/>
|
||||
""">>
|
||||
|
||||
!! Substitute a filter expression and a variable
|
||||
|
||||
The following example uses a procedure, that defines the text with substitution placeholders. `$(field)$` is defined as a variable. `${ ... }$` is filtered <<.olink2 "substitution placeholder" to:"substitute">>.
|
||||
|
||||
<<wikitext-example-without-html """\procedure field() modified
|
||||
|
||||
\procedure sentence() This tiddler was last $(field)$ on ${[{!!modified}format:date[DDth MMM YYYY]]}$
|
||||
\define name() Bugs Bunny
|
||||
\define address() Rabbit Hole Hill
|
||||
|
||||
!Substitute <<.op substitute[]>> operator parameters
|
||||
<<.operator-example 1 "[[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]]">>
|
||||
<$text text={{{ [<sentence>substitute[]] }}}/>
|
||||
|
||||
!Substitute variables
|
||||
This example uses the following variables:
|
||||
---
|
||||
|
||||
* name: <$codeblock code=<<name>>/>
|
||||
* address: <$codeblock code=<<address>>/>
|
||||
<$text text=`This tiddler was last $(field)$ on ${[{!!modified}format:date[DDth MMM YYYY]]}$`/>
|
||||
|
||||
<<.operator-example 2 "[[Hi, I'm $(name)$ and I live in $(address)$]substitute[]]">>
|
||||
|
||||
!Substitute variables and operator parameters
|
||||
This example uses the following variable:
|
||||
|
||||
* time: <$codeblock code=<<time>>/>
|
||||
|
||||
<<.operator-example 3 "[[Something in the $(time)$ at $2$ about $1$ ]substitute[Maths],[the Library]]">>
|
||||
|
||||
!Substitute a filter expression and a variable
|
||||
This example uses the following variables:
|
||||
|
||||
* field: <$codeblock code=<<field>>/>
|
||||
* sentence: <$codeblock code=<<sentence>>/>
|
||||
|
||||
<<.operator-example 4 "[<sentence>substitute[]]">>
|
||||
""">>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
caption: range
|
||||
created: 20171221184734665
|
||||
modified: 20230321133838310
|
||||
modified: 20251008154315078
|
||||
op-input: ignored
|
||||
op-neg-output: a series of evenly spaced numbers ranging from `<begin>` to `<end>` in reverse order
|
||||
op-output: a series of evenly spaced numbers ranging from `<begin>` to `<end>`
|
||||
op-neg-output: a series of evenly spaced numbers ranging from `[BEGIN]` to `[END]` in reverse order
|
||||
op-output: a series of evenly spaced numbers ranging from `[BEGIN]` to `[END]`
|
||||
op-parameter: a range specification, like `[1],[5]`
|
||||
op-parameter-name: N
|
||||
op-purpose: generate a range of numbers
|
||||
@@ -23,42 +23,56 @@ The `range` operator produces a list of numbers counting up or down. It is usef
|
||||
|
||||
<<.from-version "5.2.0">> The range operator has been updated to use multiple parameters. Prior to this version, the range operator only had one parameter, with the three parts delimited by `,`, `;` or `:`.
|
||||
|
||||
In the descriptions below the words `BEGIN`, `END` and `STEP` are placeholders.
|
||||
|
||||
```
|
||||
[range[<begin>]]
|
||||
[range[<begin>],[<end>]]
|
||||
[range[<begin>],[<end>],[<step>]]
|
||||
[range[END]]
|
||||
[range[BEGIN],[END]]
|
||||
[range[BEGIN],[END],[STEP]]
|
||||
```
|
||||
|
||||
The behaviour depends on the number of parameters:
|
||||
|
||||
|Parameter |Output |h
|
||||
|`<end>` |Whole numbers up to `<end>` |
|
||||
|`<begin>,<end>` |Numbers from `<begin>` to `<end>`, spaced by whole numbers |
|
||||
|`<begin>,<end>,<step>` |Numbers from `<begin>` to `<end>` spaced out by `<step>` |
|
||||
|Parameter(s) Literal |Output |h
|
||||
|`[END]` |Whole numbers up to `[END]` eg: `[range[7]]`|
|
||||
|`[BEGIN],[END]` |Numbers from `[BEGIN]` to `[END]`, spaced by whole numbers eg: `[range[1],[10]]` |
|
||||
|`[BEGIN],[END],[STEP]` |Numbers from `[BEGIN]` to `[END]` spaced out by `[STEP]` eg: `[range[1],[7],[2]]` |
|
||||
|
||||
Each part must be a number, and works as follows:
|
||||
|Parameter(s) Dynamic |Output |h
|
||||
|`<END>` |Whole numbers up to `<END>` eg: `[range<myRangeEnd>]`.<br>The <<.var myRangeEnd>> variable has to be defined somewhere else with eg: <<.wid let>> widget |
|
||||
|`{BEGIN},<END>` |Numbers from `{BEGIN}` to `<END>` eg: `[range{myRangeStart},<myRangeEnd>]`.<br>The <<.param myRangeStart>> will be transcluded from a tiddler "myRanageStart" and <<.var myRangeEnd>> comes from a variable |
|
||||
|
||||
* `<begin>`: start counting at this number.
|
||||
** Defaults to 1 if `<end>` is at least 1 (or -1 if `<end>` is at most -1).
|
||||
* `<end>`: stop counting at this number.
|
||||
Each parameter must be a number, and works as follows:
|
||||
|
||||
* `[BEGIN]`: start counting at this number.
|
||||
** Defaults to 1 if `[END]` is at least 1 (or -1 if `[END]` is at most -1).
|
||||
|
||||
* `[END]`: stop counting at this number.
|
||||
** This number will appear in the list unless it falls between two steps.
|
||||
* `<step>`: count up (or down) by this amount.
|
||||
|
||||
* `[STEP]`: count up (or down) by this amount.
|
||||
** Defaults to 1.
|
||||
** Cannot be zero.
|
||||
** We always count from `<begin>` toward `<end>`, whether `<step>` is positive or negative.
|
||||
** We always count from `[BEGIN]` toward `[END]`, whether `[STEP]` is positive or negative.
|
||||
|
||||
The number of decimal points in the output is fixed, and based on the parameter with the //most// decimal points.
|
||||
|
||||
To prevent the browser from freezing, `range` is currently limited to 10,000 values.
|
||||
|
||||
!!Examples
|
||||
!! Examples
|
||||
|
||||
<<range_example "7">>
|
||||
<<wikitext-example-without-html
|
||||
"""<$list variable=n filter="[range[7]]" join=", "><<n>></$list>""">>
|
||||
|
||||
<<range_example "1],[10">>
|
||||
<<wikitext-example-without-html
|
||||
"""<$list variable=n filter="[range[3],[10]]" join=", "><<n>></$list>""">>
|
||||
|
||||
<<range_example "17],[13">>
|
||||
<<wikitext-example-without-html
|
||||
"""<$list variable=n filter="[range[17],[13]]" join=", "><<n>></$list>""">>
|
||||
|
||||
<<range_example "1.001],[5],[1">>
|
||||
<<wikitext-example-without-html
|
||||
"""<$list variable=n filter="[range[1.001],[8],[2]]" join=", "><<n>></$list>""">>
|
||||
|
||||
<<wikitext-example-without-html
|
||||
"""<$list variable=n filter="[range[.9],[1.1],[.004]]" join=", "><<n>></$list>""">>
|
||||
|
||||
<<range_example ".5],[1.4],[.004">>
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: substitute
|
||||
created: 20230614223551834
|
||||
modified: 20230615173049692
|
||||
modified: 20251021124124967
|
||||
op-input: a [[selection of titles|Title Selection]]
|
||||
op-output: the input titles with placeholders for filter expressions, parameter and variables replaced with their corresponding values
|
||||
op-parameter: the <<.op substitute>> operator optionally accepts a variable number of parameters, see below for details
|
||||
@@ -18,7 +18,7 @@ The <<.op substitute>> operator replaces any placeholders in the input titles in
|
||||
# variables
|
||||
|
||||
|placeholder syntax|description|h
|
||||
|`$n$`|Text substitution of a parameter provided to the operator, where n is the position of the parameter starting with 1 for the first parameter. Unmatched placeholders pass through unchanged. |
|
||||
|`$n$`|Text substitution of a parameter provided to the operator, where n is the position of the parameter starting with 1 for the first parameter.<br>Unmatched placeholders pass through unchanged. |
|
||||
|`$(varname)$`|Text substitution of a variable. Undefined variables are replaced with an empty string. |
|
||||
|`${ filter expression }$`|Text substitution of the first result of evaluating a filter expression. In other words, if the filter returns multiple titles only the first one will be used. |
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
A <<.def filter>> is a pipeline for transforming an <<.def input>> into an <<.def output>>. Both the input and the output are [[ordered sets of titles|Title Selection]] of tiddlers and fields.
|
||||
|
||||
Filters are ''expressions'' constructed from smaller building blocks, called ''runs'', which are built using ''steps''. Eeach of which also transforms an input to an output.
|
||||
Filters are ''expressions'' constructed from smaller building blocks, called ''runs'', which are built using ''steps''. Each of which also transforms an input to an output.
|
||||
|
||||
A filter starts with an empty output. Its runs are processed from left to right, progressively modifying the output.
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
list: HelloThere [[Quick Start]] [[Find Out More]] [[TiddlyWiki on the Web]] [[Testimonials and Reviews]] GettingStarted Community
|
||||
tags: TableOfContents
|
||||
list-before:
|
||||
title: Welcome
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<list-links filter:"[tag<currentTiddler>]" >>
|
||||
@@ -1,7 +1,7 @@
|
||||
title: HelloThumbnail - Community Survey 2025
|
||||
tags: HelloThumbnail
|
||||
color:rgb(234, 205, 183)
|
||||
image: Community Survey 2025.png
|
||||
color: rgb(234, 205, 183)
|
||||
image: Community Survey 2025
|
||||
caption: Community Survey
|
||||
link: Community Survey 2025
|
||||
ribbon-text: NEW
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
background-color: #EDB431
|
||||
caption: How is ~TiddlyWiki Funded?
|
||||
color: #ff0
|
||||
image: Funding.png
|
||||
image: Funding
|
||||
link: Funding TiddlyWiki
|
||||
tags: HelloThumbnail
|
||||
title: HelloThumbnail - Funding
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
background-color: #EDB431
|
||||
caption: Intertwingled Innovations
|
||||
color: #ff0
|
||||
image: Intertwingled Innovations.png
|
||||
image: Intertwingled Innovations
|
||||
link: Intertwingled Innovations
|
||||
tags: HelloThumbnail
|
||||
title: HelloThumbnail - Intertwingled Innovations
|
||||
|
||||
@@ -4,6 +4,7 @@ color: purple
|
||||
background-color: #fff
|
||||
caption: ~MultiWikiServer
|
||||
link: MultiWikiServer
|
||||
image: MWS Banner.png
|
||||
image: MWS Banner
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Find out more about the new ~MultiWikiServer plugin that turns ~TiddlyWiki into a full-fledged server system supporting multiple user accounts and tiddler sharing
|
||||
@@ -2,7 +2,8 @@ title: HelloThumbnail - Newsletter
|
||||
tags: HelloThumbnail
|
||||
caption: ~TiddlyWiki Newsletter
|
||||
link: TiddlyWiki Newsletter
|
||||
image: TiddlyWiki Newsletter Badge.png
|
||||
image: TiddlyWiki Newsletter Badge
|
||||
color: #fff
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Subscribe to the ~TiddlyWiki Newsletter, a fortnightly summary of the most interesting and relevant news from the ~TiddlyWiki community
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
caption: Graphs and Visualizations
|
||||
color: #5778d8
|
||||
image: TW5-Graph.png
|
||||
link: TW5-Graph by Flibbles
|
||||
tags: HelloThumbnail
|
||||
title: HelloThumbnail - TW5-Graph
|
||||
ribbon-text: NEW
|
||||
|
||||
\rules except wikilink
|
||||
|
||||
Use TiddlyWiki plugins to easily create visualizations of your tiddlers.
|
||||
@@ -1,8 +1,9 @@
|
||||
title: HelloThumbnail - TiddlyWiki Privacy
|
||||
tags: HelloThumbnail
|
||||
color: #D5B7EA
|
||||
image: TiddlyWiki Privacy Badge.png
|
||||
image: TiddlyWiki Privacy Badge
|
||||
caption: Your Privacy and Security
|
||||
link: TiddlyWiki Privacy and Security
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
With care, ~TiddlyWiki can be used totally privately, without needing to trust anything or anyone but your own device
|
||||
@@ -100,11 +100,13 @@ type: text/vnd.tiddlywiki
|
||||
.yellow-note-sidebar .yellow-note {
|
||||
padding: 0.5em;
|
||||
margin: 1em 0;
|
||||
transform: rotate(-0.9deg) scale(0.95);
|
||||
transform: perspective(600px) rotateX(10deg) rotateY(5deg) scale(0.9);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.yellow-note-sidebar:hover .yellow-note {
|
||||
transform: rotate(0deg) scale(1);
|
||||
transform: perspective(900px) rotateX(5deg) rotateY(10deg) scale(0.95);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.yellow-note-sidebar:hover a {
|
||||
|
||||
@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
!! Important
|
||||
|
||||
<<.from-version "5.3.0">> It is recommended to use [[substituted attributes|Substituted Attribute Values]] or the [[substitute filter operator|substitute Operator]] to concatenate text and variables.
|
||||
Since <<.from-version "5.3.0">> it is recommended to use [[substituted attributes|Substituted Attribute Values]] or the [[substitute filter operator|substitute Operator]] to concatenate text and variables.
|
||||
|
||||
It's a frequent use case in ~TiddlyWiki that you will want to put the results of variables together with various bits of strings of text. This process in some programming languages is often referred to as "concatenating" text.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 181 KiB |
@@ -1,6 +0,0 @@
|
||||
alt-text: Shape the future by taking the TiddlyWiki Community Survey 2025
|
||||
created: 20250708125233847
|
||||
modified: 20250708125233847
|
||||
tags: picture
|
||||
title: Community Survey 2025.png
|
||||
type: image/png
|
||||
BIN
editions/tw5.com/tiddlers/images/Community Survey 2025.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,4 @@
|
||||
alt-text: Shape the future by taking the TiddlyWiki Community Survey 2025
|
||||
tags: picture
|
||||
title: Community Survey 2025
|
||||
type: image/webp
|
||||
|
Before Width: | Height: | Size: 184 KiB |
BIN
editions/tw5.com/tiddlers/images/Funding.webp
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
@@ -1,4 +1,4 @@
|
||||
title: Funding.png
|
||||
type: image/png
|
||||
title: Funding
|
||||
type: image/webp
|
||||
tags: picture
|
||||
alt-text: Hand over a debit-card.
|
||||
|
Before Width: | Height: | Size: 109 KiB |