Compare commits
65 Commits
survey-edi
...
v5.3.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae943f4906 | ||
|
|
9bdd475e60 | ||
|
|
ac83b46102 | ||
|
|
e3ced3edcb | ||
|
|
672211da15 | ||
|
|
23a23d9cac | ||
|
|
4080268887 | ||
|
|
9617a6d6d8 | ||
|
|
113eadf265 | ||
|
|
3597e6542d | ||
|
|
a467ee0816 | ||
|
|
14760da6af | ||
|
|
29a567f0a8 | ||
|
|
482af2c5d9 | ||
|
|
953792aeae | ||
|
|
047f8c7052 | ||
|
|
740018dc4c | ||
|
|
82dbc4b14c | ||
|
|
8ab4306b52 | ||
|
|
dc3d38563c | ||
|
|
00aa6efb01 | ||
|
|
0d6da12cba | ||
|
|
a785d1f4d2 | ||
|
|
7550226617 | ||
|
|
2459abcfc1 | ||
|
|
32caeb69c3 | ||
|
|
07b1502259 | ||
|
|
2a21ae5c10 | ||
|
|
9729e157cc | ||
|
|
e8a7bbf14e | ||
|
|
4f0f139a26 | ||
|
|
34889cf47b | ||
|
|
2bd4c38ee3 | ||
|
|
89030c4d4b | ||
|
|
6e7c63a72d | ||
|
|
2d75d3ccb1 | ||
|
|
f22937053b | ||
|
|
44a5d7f3dc | ||
|
|
3357da4d56 | ||
|
|
c91ef05e5b | ||
|
|
93d30f374d | ||
|
|
4a97cf35d0 | ||
|
|
c625e3c946 | ||
|
|
3e98fa0558 | ||
|
|
709c4a1b3c | ||
|
|
6e22d7eca5 | ||
|
|
67ba056832 | ||
|
|
10cf32177a | ||
|
|
b52e9d0b3e | ||
|
|
bdc0fe18fb | ||
|
|
962dbbfe16 | ||
|
|
ffb598280f | ||
|
|
0f5aa3d194 | ||
|
|
a73e03c976 | ||
|
|
4f775bed74 | ||
|
|
71232fbea2 | ||
|
|
859603961e | ||
|
|
771e963b0c | ||
|
|
ebbe6cd625 | ||
|
|
7aad7fa3e6 | ||
|
|
f8a912dfde | ||
|
|
5380472b8f | ||
|
|
f49f00b52b | ||
|
|
163adeb376 | ||
|
|
381388f9c4 |
4
.github/workflows/pr-check-build-size.yml
vendored
@@ -5,8 +5,8 @@ on:
|
||||
paths:
|
||||
- 'boot/**'
|
||||
- 'core/**'
|
||||
- 'themes/snowwhite/**'
|
||||
- 'themes/vanilla/**'
|
||||
- 'themes/tiddlywiki/snowwhite/**'
|
||||
- 'themes/tiddlywiki/vanilla/**'
|
||||
|
||||
jobs:
|
||||
calculate-build-size:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Default to the current version number for building the plugin library
|
||||
|
||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||
TW5_BUILD_VERSION=v5.3.7
|
||||
TW5_BUILD_VERSION=v5.3.8
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||
@@ -159,6 +159,13 @@ node $TW5_BUILD_TIDDLYWIKI \
|
||||
--rendertiddler $:/core/save/all-external-js tour.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# /surveys.html surveys edition
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
./editions/tiddlywiki-surveys \
|
||||
--output $TW5_BUILD_OUTPUT \
|
||||
--build index \
|
||||
|| exit 1
|
||||
|
||||
# /share.html Custom edition for sharing via the URL
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
./editions/share \
|
||||
|
||||
@@ -4,4 +4,4 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
|
||||
|
||||
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
|
||||
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
|
||||
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
|
||||
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
|
||||
|
||||
@@ -252,3 +252,6 @@ ViewTemplateSubtitle/Caption: View Template Subtitle
|
||||
ViewTemplateSubtitle/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the subtitle of a tiddler.
|
||||
ViewTemplateTags/Caption: View Template Tags
|
||||
ViewTemplateTags/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the tags area of a tiddler.
|
||||
WikiInformation/Caption: Wiki Information
|
||||
WikiInformation/Hint: This page summarises high level information about the configuration of this ~TiddlyWiki. It is designed to enable users to quickly share relevant aspects of the configuration of their ~TiddlyWiki with others, for example when seeking help in one of the forums. No private or personal information is included, and nothing is shared without being explicitly copied and pasted elsewhere
|
||||
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki
|
||||
@@ -70,7 +70,7 @@ alert-border: <<colour flexoki-ye>>
|
||||
alert-highlight: <<colour flexoki-re>>
|
||||
alert-muted-foreground: <<colour flexoki-ye>>
|
||||
background: #100F0F
|
||||
blockquote-bar: <<colour flexoki-ma-2>>
|
||||
blockquote-bar: <<colour flexoki-ma>>
|
||||
button-background: <<colour flexoki-bg-2>>
|
||||
button-foreground: <<colour flexoki-paper>>
|
||||
button-border: <<colour flexoki-600>>
|
||||
@@ -106,7 +106,7 @@ foreground: #CECDC3
|
||||
highlight-background: <<colour flexoki-yellow-900>>
|
||||
highlight-foreground: inherit
|
||||
menubar-background: <<colour primary>>
|
||||
menubar-foreground: <<colour flexoki-paper>>
|
||||
menubar-foreground: <<colour flexoki-999>>
|
||||
message-background: <<colour background>>
|
||||
message-border: <<colour foreground>>
|
||||
message-foreground: <<colour foreground>>
|
||||
|
||||
@@ -7,7 +7,7 @@ caption: {{$:/language/SideBar/Tools/Caption}}
|
||||
\procedure lingo-base() $:/language/ControlPanel/
|
||||
\function config-title() [[$:/config/PageControlButtons/Visibility/$(listItem)$]substitute[]]
|
||||
|
||||
<<lingo Basics/Version/Prompt>> <<version>>
|
||||
<<lingo Basics/Version/Prompt>><span class="tc-tiny-gap-left"><<version>></span>
|
||||
|
||||
<$let tv-config-toolbar-icons="yes"
|
||||
tv-config-toolbar-text="yes"
|
||||
|
||||
122
core/ui/WikiInformation.tid
Normal file
@@ -0,0 +1,122 @@
|
||||
title: $:/core/ui/ControlPanel/WikiInformation
|
||||
tags: $:/tags/ControlPanel/Info
|
||||
caption: <%if [[$:/language/ControlPanel/WikiInformation/Caption]is[shadow]] %>{{$:/language/ControlPanel/WikiInformation/Caption}}<%else%>Wiki Information<%endif%>
|
||||
subtitle: <%if [[$:/language/ControlPanel/WikiInformation/Caption]is[shadow]] %>{{$:/language/ControlPanel/WikiInformation/Caption}}<%else%>Wiki Information<%endif%>
|
||||
|
||||
\procedure lingo-base() $:/language/ControlPanel/WikiInformation/
|
||||
|
||||
<!--
|
||||
A custom implementation of the lingo macro that works even if this tiddler has been copied to an earlier version of TiddlyWiki that doesn't include the necessary lingo tiddlers in the core.
|
||||
-->
|
||||
|
||||
\procedure intrinsic-lingo-Hint()
|
||||
This page summarises high level information about the configuration of this ~TiddlyWiki. It is designed to enable users to quickly share relevant aspects of the configuration of their ~TiddlyWiki with others, for example when seeking help in one of the forums. No private or personal information is included, and nothing is shared without being explicitly copied and pasted elsewhere
|
||||
\end intrinsic-lingo-Hint
|
||||
|
||||
\procedure intrinsic-lingo-Drag/Caption()
|
||||
Drag this link to copy this tool to another wiki
|
||||
\end intrinsic-lingo-Drag/Caption
|
||||
|
||||
\procedure lingo(title,mode:"inline")
|
||||
<%if [<title>addprefix<lingo-base>is[shadow]] %>
|
||||
<$transclude $tiddler={{{ [<title>addprefix<lingo-base>] }}} $mode=<<mode>>/>
|
||||
<%else%>
|
||||
<$transclude $variable={{{ [<title>addprefix[intrinsic-lingo-]] }}} $mode=<<mode>>/>
|
||||
<%endif%>
|
||||
\end lingo
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure capture-item(label,value)
|
||||
<$action-setfield $tiddler=<<tempWikiInfo>> text={{{ [<tempWikiInfo>get[text]addsuffix<label>addsuffix[: ]addsuffix<value>addsuffix<crlf>] }}}/>
|
||||
\end capture-item
|
||||
|
||||
\procedure capture-item-wikified(label,value)
|
||||
<$wikify name="text" text=<<value>> mode="inline">
|
||||
<$transclude
|
||||
$variable="capture-item"
|
||||
label=<<label>>
|
||||
value=<<text>>
|
||||
/>
|
||||
</$wikify>
|
||||
\end capture-item-wikified
|
||||
|
||||
\procedure capture-wiki-info(tempWikiInfo)
|
||||
<$transclude $variable="capture-item-wikified" label="TiddlyWiki Version" value="<<version>>"/>
|
||||
<$transclude $variable="capture-item" label="Current palette" value={{$:/palette}}/>
|
||||
<$transclude $variable="capture-item" label="Current theme" value={{$:/theme}}/>
|
||||
<$transclude $variable="capture-item" label="Current layout" value={{$:/layout}}/>
|
||||
<$transclude $variable="capture-item" label="Browser language setting" value={{$:/info/browser/language}}/>
|
||||
<$transclude $variable="capture-item" label="Default type for missing tiddlers" value={{$:/config/DefaultMissingType}}/>
|
||||
<$transclude $variable="capture-item" label="Auto save setting" value={{$:/config/AutoSave}}/>
|
||||
<$transclude $variable="capture-item" label="Code wrapping setting" value={{$:/themes/tiddlywiki/vanilla/options/codewrapping}}/>
|
||||
<$transclude $variable="capture-item" label="Sticky titles setting" value={{$:/themes/tiddlywiki/vanilla/options/stickytitles}}/>
|
||||
<$transclude $variable="capture-item" label="Sidebar layout setting" value={{$:/themes/tiddlywiki/vanilla/options/sidebarlayout}}/>
|
||||
<$transclude $variable="capture-item" label="Auto focus field setting for new tiddlers" value={{$:/config/AutoFocus}}/>
|
||||
<$transclude $variable="capture-item" label="Current storyview setting" value={{$:/view}}/>
|
||||
<$transclude $variable="capture-item" label="Toolbar text setting" value={{$:/config/Toolbar/Text}}/>
|
||||
<$transclude $variable="capture-item" label="Toolbar icon setting" value={{$:/config/Toolbar/Icons}}/>
|
||||
<$transclude $variable="capture-item" label="Button class setting" value={{$:/config/Toolbar/ButtonClass}}/>
|
||||
<$transclude $variable="capture-item" label="Navigation address bar setting" value={{$:/config/Navigation/UpdateAddressBar}}/>
|
||||
<$transclude $variable="capture-item" label="Tiddler opening behaviour setting for navigations from outside the story river" value={{$:/config/Navigation/openLinkFromOutsideRiver}}/>
|
||||
<$transclude $variable="capture-item" label="Tiddler opening behaviour setting for navigations from within the story river" value={{$:/config/Navigation/openLinkFromInsideRiver}}/>
|
||||
<$transclude $variable="capture-item" label="CamelCase linking setting" value={{$:/config/WikiParserRules/Inline/wikilink}}/>
|
||||
<$transclude $variable="capture-item" label="Keyboard shortcuts that have been customised" value={{{ [all[tiddlers]prefix[$:/config/shortcuts]] +[join[,]] }}}/>
|
||||
<$transclude $variable="capture-item" label="Disabled plugins" value={{{ [all[tiddlers]prefix[$:/config/Plugins/Disabled/]] :filter[{!!text}match[yes]] :map[<currentTiddler>removeprefix[$:/config/Plugins/Disabled/]] +[join[,]] }}}/>
|
||||
<$transclude $variable="capture-item" label="Plugins" value={{{ [has[plugin-type]sort[]] :filter[<currentTiddler>addprefix[$:/config/Plugins/Disabled/]get[text]else[no]!match[yes]] :map[{!!version}addprefix[ - ]addprefix<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
|
||||
\end capture-wiki-info
|
||||
|
||||
\procedure template-header()
|
||||
<details><summary>Wiki Information</summary><pre><code>
|
||||
|
||||
\end template-header
|
||||
|
||||
\procedure template-footer()
|
||||
|
||||
</code></pre></details>
|
||||
\end template-footer
|
||||
|
||||
\procedure display-wiki-info-modal()
|
||||
<$let
|
||||
tempWikiInfo="$:/temp/wiki-info"
|
||||
crlf={{{ [charcode[13],[10]] }}}
|
||||
>
|
||||
<$action-sendmessage
|
||||
$message="tm-modal"
|
||||
$param="$:/core/ui/ControlPanel/WikiInformation"
|
||||
isModal="yes"
|
||||
tempWikiInfo=<<tempWikiInfo>>
|
||||
/>
|
||||
<$action-deletetiddler $tiddler=<<tempWikiInfo>>/>
|
||||
<$action-setfield $tiddler=<<tempWikiInfo>> text=<<template-header>>/>
|
||||
<$transclude
|
||||
$variable="capture-wiki-info"
|
||||
tempWikiInfo=<<tempWikiInfo>>
|
||||
/>
|
||||
<$action-setfield $tiddler=<<tempWikiInfo>> text={{{ [<tempWikiInfo>get[text]addsuffix<template-footer>] }}}/>
|
||||
</$let>
|
||||
\end display-wiki-info-modal
|
||||
|
||||
\procedure story-content()
|
||||
<<lingo title:"Hint" mode:"block">>
|
||||
|
||||
<$button>
|
||||
<<display-wiki-info-modal>>
|
||||
Click to generate wiki information report
|
||||
</$button>
|
||||
|
||||
<$link to="$:/core/ui/ControlPanel/WikiInformation">
|
||||
<<lingo title:"Drag/Caption" mode:"inline">>
|
||||
</$link>
|
||||
\end story-content
|
||||
|
||||
\procedure modal-content()
|
||||
<p>
|
||||
<$transclude $variable="copy-to-clipboard" src={{{ [<tempWikiInfo>get[text]] }}}/>
|
||||
</p>
|
||||
<p>
|
||||
<$edit-text tiddler=<<tempWikiInfo>> tag="textarea" disabled="yes" class="tc-max-width"/>
|
||||
</p>
|
||||
\end modal-content
|
||||
|
||||
<$transclude $variable={{{ [<isModal>match[yes]then[modal-content]else[story-content]] }}} $mode="block"/>
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/library/v5.3.7/index.html
|
||||
url: https://tiddlywiki.com/library/v5.3.8/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}}
|
||||
|
||||
{{$:/language/OfficialPluginLibrary/Hint}}
|
||||
|
||||
@@ -1,55 +1,58 @@
|
||||
title: $:/core/macros/colour-picker
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\procedure colour-picker-update-recent()
|
||||
\define colour-picker-update-recent()
|
||||
<$action-listops
|
||||
$tiddler="$:/config/ColourPicker/Recent"
|
||||
$subfilter="[<colour-picker-value>] [list[$:/config/ColourPicker/Recent]remove<colour-picker-value>] +[limit[8]]"
|
||||
$subfilter="$(colour-picker-value)$ [list[$:/config/ColourPicker/Recent]remove[$(colour-picker-value)$]] +[limit[8]]"
|
||||
/>
|
||||
\end
|
||||
|
||||
\procedure colour-picker-inner(actions)
|
||||
<$button tag="a" tooltip=<<colour-picker-value>>>
|
||||
<<colour-picker-update-recent>>
|
||||
<$transclude $variable="actions"/>
|
||||
<span style.display="inline-block" style.backgroundColor=<<colour-picker-value>> style.width="100%" style.height="100%" style.borderRadius="50%"/>
|
||||
\define colour-picker-inner(actions)
|
||||
<$button tag="a" tooltip="""$(colour-picker-value)$""">
|
||||
$(colour-picker-update-recent)$
|
||||
<$transclude $variable="__actions__"/>
|
||||
|
||||
<span style="display:inline-block; background-color: $(colour-picker-value)$; width: 100%; height: 100%; border-radius: 50%;"/>
|
||||
|
||||
</$button>
|
||||
\end
|
||||
|
||||
\define colour-picker-recent-inner(actions)
|
||||
\whitespace trim
|
||||
\procedure colour-picker-recent-inner(actions)
|
||||
<$set name="colour-picker-value" value=<<recentColour>>>
|
||||
<$transclude $variable="colour-picker-inner" actions=<<actions>>/>
|
||||
<$set name="colour-picker-value" value="$(recentColour)$">
|
||||
<$macrocall $name="colour-picker-inner" actions=<<__actions__>>/>
|
||||
</$set>
|
||||
\end
|
||||
|
||||
\procedure colour-picker-recent(actions)
|
||||
\define colour-picker-recent(actions)
|
||||
\whitespace trim
|
||||
{{$:/language/ColourPicker/Recent}}<$list filter="[list[$:/config/ColourPicker/Recent]]" variable="recentColour">
|
||||
 
|
||||
<$transclude $variable="colour-picker-recent-inner" actions=<<actions>>/>
|
||||
<$macrocall $name="colour-picker-recent-inner" actions=<<__actions__>>/>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
\procedure colour-picker(actions)
|
||||
\define colour-picker(actions)
|
||||
\whitespace trim
|
||||
<div class="tc-colour-chooser">
|
||||
|
||||
<$transclude $variable="colour-picker-recent" actions=<<actions>>/>
|
||||
<$macrocall $name="colour-picker-recent" actions=<<__actions__>>/>
|
||||
|
||||
---
|
||||
|
||||
<$list filter="LightPink Pink Crimson LavenderBlush PaleVioletRed HotPink DeepPink MediumVioletRed Orchid Thistle Plum Violet Magenta Fuchsia DarkMagenta Purple MediumOrchid DarkViolet DarkOrchid Indigo BlueViolet MediumPurple MediumSlateBlue SlateBlue DarkSlateBlue Lavender GhostWhite Blue MediumBlue MidnightBlue DarkBlue Navy RoyalBlue CornflowerBlue LightSteelBlue LightSlateGrey SlateGrey DodgerBlue AliceBlue SteelBlue LightSkyBlue SkyBlue DeepSkyBlue LightBlue PowderBlue CadetBlue Azure LightCyan PaleTurquoise Cyan Aqua DarkTurquoise DarkSlateGrey DarkCyan Teal MediumTurquoise LightSeaGreen Turquoise Aquamarine MediumAquamarine MediumSpringGreen MintCream SpringGreen MediumSeaGreen SeaGreen Honeydew LightGreen PaleGreen DarkSeaGreen LimeGreen Lime ForestGreen Green DarkGreen Chartreuse LawnGreen GreenYellow DarkOliveGreen YellowGreen OliveDrab Beige LightGoldenrodYellow Ivory LightYellow Yellow Olive DarkKhaki LemonChiffon PaleGoldenrod Khaki Gold Cornsilk Goldenrod DarkGoldenrod FloralWhite OldLace Wheat Moccasin Orange PapayaWhip BlanchedAlmond NavajoWhite AntiqueWhite Tan BurlyWood Bisque DarkOrange Linen Peru PeachPuff SandyBrown Chocolate SaddleBrown Seashell Sienna LightSalmon Coral OrangeRed DarkSalmon Tomato MistyRose Salmon Snow LightCoral RosyBrown IndianRed Red Brown FireBrick DarkRed Maroon White WhiteSmoke Gainsboro LightGrey Silver DarkGrey Grey DimGrey Black" variable="colour-picker-value">
|
||||
 
|
||||
<$transclude $variable="colour-picker-inner" actions=<<actions>>/>
|
||||
<$macrocall $name="colour-picker-inner" actions=<<__actions__>>/>
|
||||
</$list>
|
||||
|
||||
---
|
||||
|
||||
<$edit-text tiddler="$:/config/ColourPicker/New" tag="input" default="" placeholder="" class="tc-tiny-gap-right"/>
|
||||
<$edit-text tiddler="$:/config/ColourPicker/New" tag="input" default="" placeholder=""/>
|
||||
 
|
||||
<$edit-text tiddler="$:/config/ColourPicker/New" type="color" tag="input"/>
|
||||
<$set name="colour-picker-value" value={{$:/config/ColourPicker/New}}>
|
||||
<%if [{$:/config/ColourPicker/New}!is[blank]] %>
|
||||
<$transclude $variable="colour-picker-inner" actions=<<actions>>/>
|
||||
<%endif%>
|
||||
<$macrocall $name="colour-picker-inner" actions=<<__actions__>>/>
|
||||
</$set>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
title: $:/core/macros/dumpvariables
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\procedure dumpvariables()
|
||||
\define dumpvariables()
|
||||
\whitespace trim
|
||||
<ul>
|
||||
<$list filter="[variables[]]" variable="varname">
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
created: 20170715180840889
|
||||
modified: 20170715180914005
|
||||
tags: $:/tags/Macro
|
||||
title: $:/core/macros/image-picker
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\procedure image-picker-thumbnail(actions)
|
||||
<$button tag="a" tooltip=<<imageTitle>>><$transclude $variable="actions"/><$transclude tiddler=<<imageTitle>>/></$button>
|
||||
\define image-picker-thumbnail(actions)
|
||||
<$button tag="a" tooltip="""$(imageTitle)$"""><$transclude $variable="__actions__"/><$transclude tiddler=<<imageTitle>>/></$button>
|
||||
\end
|
||||
|
||||
\procedure image-picker-list(filter,actions)
|
||||
\define image-picker-list(filter,actions)
|
||||
\whitespace trim
|
||||
<$list filter=<<filter>> variable="imageTitle">
|
||||
<$transclude $variable="image-picker-thumbnail" actions=<<actions>>/>
|
||||
<$list filter="""$filter$""" variable="imageTitle">
|
||||
<$macrocall $name="image-picker-thumbnail" actions=<<__actions__>>/>
|
||||
 
|
||||
</$list>
|
||||
\end
|
||||
|
||||
\procedure image-picker(actions,filter:"[all[shadows+tiddlers]is[image]] -[type[application/pdf]] +[!has[draft.of]$subfilter$sort[title]]",subfilter:"")
|
||||
\define image-picker(actions,filter:"[all[shadows+tiddlers]is[image]] -[type[application/pdf]] +[!has[draft.of]$subfilter$sort[title]]",subfilter:"")
|
||||
\whitespace trim
|
||||
<div class="tc-image-chooser">
|
||||
<$let state-system=<<qualify "$:/state/image-picker/system">> tv-filter={{{ [<filter>search-replace[$subfilter$],<subfilter>] }}}>
|
||||
<$vars state-system=<<qualify "$:/state/image-picker/system">>>
|
||||
<$checkbox tiddler=<<state-system>> field="text" checked="show" unchecked="hide" default="hide">
|
||||
<span class="tc-tiny-gap-left">{{$:/language/SystemTiddlers/Include/Prompt}}</span>
|
||||
 
|
||||
{{$:/language/SystemTiddlers/Include/Prompt}}
|
||||
</$checkbox>
|
||||
<$reveal state=<<state-system>> type="match" text="hide" default="hide" tag="div">
|
||||
<$transclude $variable="image-picker-list" filter=`$(tv-filter)$ +[!is[system]]` actions=<<actions>>/>
|
||||
<$macrocall $name="image-picker-list" filter="""$filter$ +[!is[system]]""" actions=<<__actions__>>/>
|
||||
</$reveal>
|
||||
<$reveal state=<<state-system>> type="nomatch" text="hide" default="hide" tag="div">
|
||||
<$transclude $variable="image-picker-list" filter=<<tv-filter>> actions=<<actions>>/>
|
||||
<$macrocall $name="image-picker-list" filter="""$filter$""" actions=<<__actions__>>/>
|
||||
</$reveal>
|
||||
</$let>
|
||||
</$vars>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\procedure image-picker-include-tagged-images(actions)
|
||||
<$transclude $variable="image-picker" filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]" actions=<<actions>>/>
|
||||
\define image-picker-include-tagged-images(actions)
|
||||
<$macrocall $name="image-picker" filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]" actions=<<__actions__>>/>
|
||||
\end
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
title: $:/core/macros/list
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\procedure list-links-draggable-drop-actions()
|
||||
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||
\end
|
||||
|
||||
\define list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage,field:"caption")
|
||||
\whitespace trim
|
||||
\procedure list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage,field:"caption")
|
||||
<$genesis $type=<<type>> class=<<class>>>
|
||||
<$list filter=<<filter>> emptyMessage=<<emptyMessage>>>
|
||||
<$genesis $type=<<subtype>>>
|
||||
<$genesis $type=<<__type__>> class=<<__class__>>>
|
||||
<$list filter=<<__filter__>> emptyMessage=<<__emptyMessage__>>>
|
||||
<$genesis $type=<<__subtype__>>>
|
||||
<$link to={{!!title}}>
|
||||
<$let tv-wikilinks="no">
|
||||
<$transclude field=<<field>>>
|
||||
<$transclude field=<<__field__>>>
|
||||
<$view field="title"/>
|
||||
</$transclude>
|
||||
</$let>
|
||||
@@ -22,19 +18,24 @@ tags: $:/tags/Macro
|
||||
</$genesis>
|
||||
\end
|
||||
|
||||
\procedure list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
|
||||
\define list-links-draggable-drop-actions()
|
||||
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||
\end
|
||||
|
||||
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
|
||||
\whitespace trim
|
||||
<span class="tc-links-draggable-list">
|
||||
<$let targetTiddler=<<tiddler>> targetField=<<field>>>
|
||||
<$genesis $type=<<type>> class=<<class>>>
|
||||
<$list filter="[<tiddler>get<field>enlist-input[]]" emptyMessage=<<emptyMessage>>>
|
||||
<$vars targetTiddler="""$tiddler$""" targetField="""$field$""">
|
||||
<$genesis $type=<<__type__>> class="$class$">
|
||||
<$list filter="[list[$tiddler$!!$field$]]" emptyMessage=<<__emptyMessage__>>>
|
||||
<$droppable
|
||||
actions=<<list-links-draggable-drop-actions>>
|
||||
tag=<<subtype>>
|
||||
tag="""$subtype$"""
|
||||
enable=<<tv-enable-drag-and-drop>>
|
||||
>
|
||||
<div class="tc-droppable-placeholder"/>
|
||||
<div>
|
||||
<$transclude tiddler=<<itemTemplate>>>
|
||||
<$transclude tiddler="""$itemTemplate$""">
|
||||
<$link to={{!!title}}>
|
||||
<$let tv-wikilinks="no">
|
||||
<$transclude field="caption">
|
||||
@@ -59,54 +60,52 @@ tags: $:/tags/Macro
|
||||
</$droppable>
|
||||
</$tiddler>
|
||||
</$genesis>
|
||||
</$let>
|
||||
</$vars>
|
||||
</span>
|
||||
\end
|
||||
|
||||
\procedure list-tagged-draggable-drop-actions(tag)
|
||||
\define list-tagged-draggable-drop-actions(tag)
|
||||
\whitespace trim
|
||||
<!-- Save the current ordering of the tiddlers with this tag -->
|
||||
<$set name="order" filter="[<tag>tagging[]]">
|
||||
<$set name="order" filter="[<__tag__>tagging[]]">
|
||||
<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->
|
||||
<$list filter="[<tag>tagging[]]">
|
||||
<$list filter="[<__tag__>tagging[]]">
|
||||
<$action-deletefield $field="list-before"/>
|
||||
<$action-deletefield $field="list-after"/>
|
||||
</$list>
|
||||
<!-- Save the new order to the Tag Tiddler -->
|
||||
<$action-listops $tiddler=<<tag>> $field="list" $filter="+[enlist<order>] +[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||
<$action-listops $tiddler=<<__tag__>> $field="list" $filter="+[enlist<order>] +[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||
<!-- Make sure the newly added item has the right tag -->
|
||||
<!-- Removing this line makes dragging tags within the dropdown work as intended -->
|
||||
<!--<$action-listops $tiddler=<<actionTiddler>> $tags=<<tag>>/>-->
|
||||
<!--<$action-listops $tiddler=<<actionTiddler>> $tags=<<__tag__>>/>-->
|
||||
<!-- Using the following 5 lines as replacement makes dragging titles from outside into the dropdown apply the tag -->
|
||||
<$list filter="[<actionTiddler>!contains:tags<tag>]">
|
||||
<$list filter="[<actionTiddler>!contains:tags<__tag__>]">
|
||||
<$fieldmangler tiddler=<<actionTiddler>>>
|
||||
<$action-sendmessage $message="tm-add-tag" $param=<<tag>>/>
|
||||
<$action-sendmessage $message="tm-add-tag" $param=<<__tag__>>/>
|
||||
</$fieldmangler>
|
||||
</$list>
|
||||
</$set>
|
||||
\end
|
||||
|
||||
\procedure list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"")
|
||||
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"")
|
||||
\whitespace trim
|
||||
<span class="tc-tagged-draggable-list">
|
||||
<$set name="tag" value=<<tag>>>
|
||||
<$set name="tag" value=<<__tag__>>>
|
||||
<$list
|
||||
filter=`[<tag>tagging[]$(subFilter)$]`
|
||||
emptyMessage=<<emptyMessage>>
|
||||
storyview=<<storyview>>
|
||||
filter="[<__tag__>tagging[]$subFilter$]"
|
||||
emptyMessage=<<__emptyMessage__>>
|
||||
storyview=<<__storyview__>>
|
||||
>
|
||||
<$genesis $type=<<elementTag>> class="tc-menu-list-item">
|
||||
<$genesis $type=<<__elementTag__>> class="tc-menu-list-item">
|
||||
<$droppable
|
||||
actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<tag>>/>"""
|
||||
actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>"""
|
||||
enable=<<tv-enable-drag-and-drop>>
|
||||
>
|
||||
<$genesis $type=<<elementTag>> class="tc-droppable-placeholder"/>
|
||||
<$genesis $type=<<elementTag>>>
|
||||
<$transclude tiddler=<<itemTemplate>>>
|
||||
<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/>
|
||||
<$genesis $type=<<__elementTag__>>>
|
||||
<$transclude tiddler="""$itemTemplate$""">
|
||||
<$link to={{!!title}}>
|
||||
<$let tv-wikilinks="no">
|
||||
<$transclude field="caption">
|
||||
<$view field="title"/>
|
||||
</$transclude>
|
||||
</$let>
|
||||
<$view field="title"/>
|
||||
</$link>
|
||||
</$transclude>
|
||||
</$genesis>
|
||||
@@ -115,11 +114,11 @@ tags: $:/tags/Macro
|
||||
</$list>
|
||||
<$tiddler tiddler="">
|
||||
<$droppable
|
||||
actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<tag>>/>"""
|
||||
actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>"""
|
||||
enable=<<tv-enable-drag-and-drop>>
|
||||
>
|
||||
<$genesis $type=<<elementTag>> class="tc-droppable-placeholder"/>
|
||||
<$genesis $type=<<elementTag>> style="height:0.5em;"/>
|
||||
<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/>
|
||||
<$genesis $type=<<__elementTag__>> style="height:0.5em;"/>
|
||||
</$droppable>
|
||||
</$tiddler>
|
||||
</$set>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
title: $:/core/macros/translink
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\procedure translink(title,mode:"block")
|
||||
\define translink(title,mode:"block")
|
||||
\whitespace trim
|
||||
<%if [<mode>match[block]] %>
|
||||
<$list filter="[<__mode__>match[block]]">
|
||||
<div class="tc-translink">
|
||||
<div>
|
||||
<$link to=<<title>>>
|
||||
<h1><$text text=<<title>>/></h1>
|
||||
<$link to="""$title$""">
|
||||
<h1><$text text="""$title$"""/></h1>
|
||||
</$link>
|
||||
<$transclude tiddler=<<title>> mode="block">
|
||||
<$set name="currentTiddler" value=<<title>>><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
<$transclude tiddler="""$title$""" mode="block">
|
||||
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
</$transclude>
|
||||
</div>
|
||||
</div>
|
||||
<%endif%>
|
||||
<%if [<mode>match[inline]] %>
|
||||
</$list>
|
||||
<$list filter="[<__mode__>match[inline]]">
|
||||
<span class="tc-translink">
|
||||
<$link to=<<title>> class="tc-tiny-gap-right">
|
||||
<$text text=<<title>>/>
|
||||
<$link to="""$title$""">
|
||||
<$text text="""$title$"""/>
|
||||
</$link>
|
||||
(<$transclude tiddler=<<title>> mode="inline">
|
||||
<$set name="currentTiddler" value=<<title>>><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
 (<$transclude tiddler="""$title$""" mode="inline">
|
||||
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
</$transclude>)
|
||||
</span>
|
||||
<%endif%>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
@@ -1,58 +1,62 @@
|
||||
title: $:/core/macros/tree
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\procedure leaf-link(full-title,chunk,separator: "/")
|
||||
<$link to=<<full-title>>><$text text=<<chunk>>/></$link>
|
||||
\define leaf-link(full-title,chunk,separator: "/")
|
||||
<$link to=<<__full-title__>>><$text text=<<__chunk__>>/></$link>
|
||||
\end
|
||||
|
||||
\define leaf-node(prefix,chunk)
|
||||
\whitespace trim
|
||||
\procedure leaf-node(prefix,chunk)
|
||||
<li>
|
||||
<$list filter="[<prefix>addsuffix<chunk>is[shadow]] [<prefix>addsuffix<chunk>is[tiddler]]" variable="full-title">
|
||||
<$list filter="[<full-title>removeprefix<prefix>]" variable="chunk">
|
||||
<span class="tc-tiny-gap-right">{{$:/core/images/file}}</span><$transclude $variable="leaf-link" full-title=<<full-title>> chunk=<<chunk>>/>
|
||||
<$list filter="[<__prefix__>addsuffix<__chunk__>is[shadow]] [<__prefix__>addsuffix<__chunk__>is[tiddler]]" variable="full-title">
|
||||
<$list filter="[<full-title>removeprefix<__prefix__>]" variable="chunk">
|
||||
<span>{{$:/core/images/file}}</span> <$macrocall $name="leaf-link" full-title=<<full-title>> chunk=<<chunk>>/>
|
||||
</$list>
|
||||
</$list>
|
||||
</li>
|
||||
\end
|
||||
|
||||
\procedure branch-node(prefix,chunk,separator: "/")
|
||||
\define branch-node(prefix,chunk,separator: "/")
|
||||
\whitespace trim
|
||||
<li>
|
||||
<$set name="reveal-state" value={{{ [[$:/state/tree/]addsuffix<prefix>addsuffix<chunk>] }}}>
|
||||
<$set name="reveal-state" value={{{ [[$:/state/tree/]addsuffix<__prefix__>addsuffix<__chunk__>] }}}>
|
||||
<$reveal type="nomatch" stateTitle=<<reveal-state>> text="show">
|
||||
<$button setTitle=<<reveal-state>> setTo="show" class="tc-btn-invisible">
|
||||
{{$:/core/images/folder}} <$text text=<<chunk>>/>
|
||||
{{$:/core/images/folder}} <$text text=<<__chunk__>>/>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" stateTitle=<<reveal-state>> text="show">
|
||||
<$button setTitle=<<reveal-state>> setTo="hide" class="tc-btn-invisible">
|
||||
{{$:/core/images/folder}} <$text text=<<chunk>>/>
|
||||
{{$:/core/images/folder}} <$text text=<<__chunk__>>/>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<span class="tc-tiny-gap-left">(<$count filter="[all[shadows+tiddlers]removeprefix<prefix>removeprefix<chunk>] -[<prefix>addsuffix<chunk>]"/>)</span>
|
||||
 
|
||||
<span>(<$count filter="[all[shadows+tiddlers]removeprefix<__prefix__>removeprefix<__chunk__>] -[<__prefix__>addsuffix<__chunk__>]"/>)</span>
|
||||
<$reveal type="match" stateTitle=<<reveal-state>> text="show">
|
||||
<$transclude $variable="tree-node" prefix={{{ [<prefix>addsuffix<chunk>] }}} separator=<<separator>>/>
|
||||
<$macrocall $name="tree-node" prefix={{{ [<__prefix__>addsuffix<__chunk__>] }}} separator=<<__separator__>>/>
|
||||
</$reveal>
|
||||
</$set>
|
||||
</li>
|
||||
\end
|
||||
|
||||
\procedure tree-node(prefix,separator: "/")
|
||||
\define tree-node(prefix,separator: "/")
|
||||
\whitespace trim
|
||||
<ol>
|
||||
<$list filter="[all[shadows+tiddlers]removeprefix<prefix>splitbefore<separator>sort[]!suffix<separator>]" variable="chunk">
|
||||
<$transclude $variable="leaf-node" prefix=<<prefix>> chunk=<<chunk>> separator=<<separator>>/>
|
||||
<$list filter="[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]!suffix<__separator__>]" variable="chunk">
|
||||
<$macrocall $name="leaf-node" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>
|
||||
</$list>
|
||||
<$list filter="[all[shadows+tiddlers]removeprefix<prefix>splitbefore<separator>sort[]suffix<separator>]" variable="chunk">
|
||||
<$transclude $variable="branch-node" prefix=<<prefix>> chunk=<<chunk>> separator=<<separator>>/>
|
||||
<$list filter="[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]suffix<__separator__>]" variable="chunk">
|
||||
<$macrocall $name="branch-node" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>
|
||||
</$list>
|
||||
</ol>
|
||||
\end
|
||||
|
||||
\procedure tree(prefix: "$:/",separator: "/")
|
||||
\define tree(prefix: "$:/",separator: "/")
|
||||
\whitespace trim
|
||||
<div class="tc-tree">
|
||||
<span><$text text=<<prefix>>/></span>
|
||||
<span><$text text=<<__prefix__>>/></span>
|
||||
<div>
|
||||
<$transclude $variable="tree-node" prefix=<<prefix>> separator=<<separator>>/>
|
||||
<$macrocall $name="tree-node" prefix=<<__prefix__>> separator=<<__separator__>>/>
|
||||
</div>
|
||||
</div>
|
||||
\end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20190809095728085
|
||||
modified: 20190809123445125
|
||||
modified: 20250707151538845
|
||||
title: Releasing a new version of TiddlyWiki
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -11,36 +11,40 @@ type: text/vnd.tiddlywiki
|
||||
# Move the latest release note from the prerelease edition into the tw5.com edition
|
||||
# Adjust the release date and the ''released'' field of the latest release tiddler (eg, [[Release 5.1.3]])
|
||||
# Also adjust the github.com comparison link to point to the tag for the new release
|
||||
# Adjust the tiddler [[TiddlyWiki Archive]] to include the new version number
|
||||
# Ensure [[TiddlyWiki Releases]] has the new version as the default tab
|
||||
# Adjust the modified time of HelloThere
|
||||
# Make sure ''master'' is fully committed
|
||||
|
||||
!! Update Readmes
|
||||
!! Update Readmes and release note
|
||||
|
||||
# Edit `package.json` to the new version number
|
||||
# Run `./bin/readme-bld.sh` to build the readme files
|
||||
# Commit the new readme files to ''master''
|
||||
# Restore `package.json` to the previous version number
|
||||
# Adjust the link for "GitHub for detailed change history of this release" in the release note
|
||||
# Add the credits for the new release banner to the release note, including a link to the GitHub instance of the image from the commit history
|
||||
|
||||
!! Make New Release
|
||||
|
||||
# Run `./bin/verbump "5.1.3"` (substituting the correct version number) to update the version number, assign it a tag
|
||||
# Run `./bin/verbump "5.1.3"` (substituting the correct version number) to update the version number and assign it a tag
|
||||
# Run `./bin/npm-publish.sh` to publish the release to npm
|
||||
# Verify that the new release of TiddlyWiki is available at https://www.npmjs.org/package/tiddlywiki
|
||||
|
||||
!! Update tiddlywiki.com release
|
||||
|
||||
# Update ''tiddlywiki-com'' from ''master'' and push to ~GitHub
|
||||
# Wait until https://tiddlywiki.com is updated with the new release
|
||||
|
||||
!! Cleaning Up
|
||||
!! Announcements
|
||||
|
||||
# Tweet the release with the text "TiddlyWiki v5.x.x released to https://tiddlywiki.com #newtiddlywikirelease"
|
||||
# Announce the new release on [[TalkTW|https://talk.tiddlywiki.org]]
|
||||
|
||||
!! Preparation for the next release in ''master''
|
||||
|
||||
# Adjust version number in `package.json`
|
||||
# Adjust version number in `bin/build-site.sh`
|
||||
# Adjust version number in [[$:/config/OfficialPluginLibrary]] (both in `editions/tw5.com` and `editions/prerelease/tiddlers/system`) and [[$:/config/LocalPluginLibrary]]
|
||||
# Adjust new release banner
|
||||
# Create temporary new release banner
|
||||
# Create the release note for the new release
|
||||
# Commit changes to ''master'' and push to ~GitHub
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.3.7/index.html
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.3.8/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease)
|
||||
|
||||
The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||
|
||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 826 B |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 577 B |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,191 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,360 @@
|
||||
/***
|
||||
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";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,373 @@
|
||||
/***
|
||||
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));
|
||||
//}}}
|
||||
@@ -0,0 +1,42 @@
|
||||
/***
|
||||
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);
|
||||
//}}}
|
||||
@@ -0,0 +1,108 @@
|
||||
/***
|
||||
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);
|
||||
//}}}
|
||||
@@ -0,0 +1,57 @@
|
||||
/***
|
||||
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));
|
||||
//}}}
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,406 @@
|
||||
/*! 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;
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,2 @@
|
||||
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"};
|
||||
@@ -0,0 +1,766 @@
|
||||
/***
|
||||
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));
|
||||
//}}}
|
||||
@@ -0,0 +1,3 @@
|
||||
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,73 @@
|
||||
function stringifyList(value) {
|
||||
if(Array.isArray(value)) {
|
||||
var result = new Array(value.length);
|
||||
for(var t=0, l=value.length; t<l; t++) {
|
||||
var entry = value[t] || "";
|
||||
if(entry.match(/[^\S\xA0]/mg)) {
|
||||
result[t] = "[[" + entry + "]]";
|
||||
} else {
|
||||
result[t] = entry;
|
||||
}
|
||||
}
|
||||
return result.join(" ");
|
||||
} else {
|
||||
return value || "";
|
||||
}
|
||||
};
|
||||
|
||||
const tiddlers=[];
|
||||
const questions = [];
|
||||
const siteIconByUsername = {};
|
||||
for(const child of document.querySelector("#tiddlerDisplay").childNodes) {
|
||||
const titlePrefix = "2010 - ";
|
||||
const title = child.getAttribute("tiddler");
|
||||
if(title !== "HelloThere") {
|
||||
questions.push(titlePrefix + title);
|
||||
const childTitles = [];
|
||||
const children = title === "What do you think of the name TiddlyWiki and the term \"tiddler\"?" ? child.querySelectorAll("div.content > div.viewer > div.resultsArea > ul > li") : child.querySelectorAll("div.resultsArea > ul > li");
|
||||
for(const answer of children) {
|
||||
const siteIconName = answer.querySelector(".siteIcon img").src.split("/").pop();
|
||||
const username = answer.innerText.split("\n\n")[0].split(" ")[1];
|
||||
const answerDate = new Date(answer.innerText.split("\n\n")[0].split(" on ")[1]);
|
||||
const answerHTML = answer.querySelector("blockquote").innerHTML;
|
||||
const childTitle = titlePrefix + title + " - " + username + " - " + answerDate.toISOString();
|
||||
// console.log(`${username} has site icon ${siteIconName}`);
|
||||
siteIconByUsername[username] = siteIconName;
|
||||
childTitles.push(childTitle);
|
||||
tiddlers.push({
|
||||
title: childTitle,
|
||||
text: answerHTML,
|
||||
icon: `$:/avatars/${username}`,
|
||||
modifier: username,
|
||||
modified: answerDate.toISOString().slice(0, 10).replace(/-/g, '') + "000000000",
|
||||
tags: stringifyList([titlePrefix + title,"2010 - Interview Answer"])
|
||||
});
|
||||
}
|
||||
tiddlers.push({
|
||||
title: titlePrefix + title,
|
||||
list: stringifyList(childTitles.reverse()),
|
||||
tags: "[[2010 - Interview Question]]"
|
||||
});
|
||||
}
|
||||
}
|
||||
tiddlers.push({
|
||||
title: "2010 - Interview Question",
|
||||
list: stringifyList(questions)
|
||||
})
|
||||
copy(JSON.stringify(tiddlers,null,4));
|
||||
|
||||
const commands = [
|
||||
"mkdir -p ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/images/"
|
||||
];
|
||||
for(const username in siteIconByUsername) {
|
||||
|
||||
commands.push(`cp './editions/tiddlywiki-surveys/great-interview-project-2010/The great TiddlyWiki interview project_files/${siteIconByUsername[username]}' './editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/images/${username}.jpg'`);
|
||||
const metafile = `title: $:/avatars/${username}
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: ${username}
|
||||
`;
|
||||
|
||||
commands.push(`echo "${metafile}" > './editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/images/${username}.jpg.meta'`);
|
||||
}
|
||||
console.log(commands.join(" && "));
|
||||
12
editions/tiddlywiki-surveys/scripts/import-great-interview-project-json.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Load the Great Interview Project JSON data into TiddlyWiki and then save it to the specified folder as .tid files
|
||||
rm -rf ./tmp/2010-great-interview-project
|
||||
node ./tiddlywiki.js --load ./tmp/2010-great-interview-project.json --savewikifolder ./tmp/2010-great-interview-project
|
||||
|
||||
# Copy the tiddlers into this wiki
|
||||
rm -rf ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project
|
||||
mkdir ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project
|
||||
mkdir ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/text
|
||||
mkdir ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/images
|
||||
cp ./tmp/2010-great-interview-project/tiddlers/2010* ./editions/tiddlywiki-surveys/tiddlers/2010-great-interview-project/text
|
||||
16
editions/tiddlywiki-surveys/scripts/readme.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Utility Scripts
|
||||
|
||||
This folder contains tools used to extract the tiddlers from the original HTML file.
|
||||
|
||||
All pathnames in these instructions are relative to the root of this repository.
|
||||
|
||||
1. Load `./editions/tiddlywiki-surveys/great-interview-project-2010/The great TiddlyWiki interview project.htm` in a browser
|
||||
2. Open the developer console and paste the script from `./editions/tiddlywiki-surveys/scripts/extract-text-tiddlers-via-console.js`. The JSON representation of the text tiddlers will be generated and copied to the clipboard
|
||||
3. Paste the resulting JSON into `2010-great-interview-project.json` in the `./tmp` folder in the root of this repository
|
||||
4. Open a terminal console in the root of this repository
|
||||
5. Run the script `./editions/tiddlywiki-surveys/scripts/import-great-interview-project-json.sh`
|
||||
6. Go back to the developer console and copy the text that was output by the previous line. This is quite tricky: it's a big block of text including newlines. It is easiest to scroll back up to find the line starting with `mkdir -p` and then select down to the bottom
|
||||
7. Paste the results of the previous into the terminal
|
||||
8. Build the wiki with `node ./tiddlywiki.js ./editions/tiddlywiki-surveys --build index`
|
||||
|
||||
The resulting wiki will be found in `./editions/tiddlywiki-surveys/output/index.html`.
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/aamaadmitw5
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: aamaadmitw5
|
||||
|
||||
|
After Width: | Height: | Size: 826 B |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/alexhough
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: alexhough
|
||||
|
||||
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/amalfaro-wrk
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: amalfaro-wrk
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/andrewbarbour
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: andrewbarbour
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/calmo
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: calmo
|
||||
|
||||
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/climatechange3
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: climatechange3
|
||||
|
||||
|
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/colmbritton
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: colmbritton
|
||||
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/dickon
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: dickon
|
||||
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/frankfurtkid
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: frankfurtkid
|
||||
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/gjrobert
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: gjrobert
|
||||
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/kosmaton
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: kosmaton
|
||||
|
||||
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/mama
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: mama
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/martinlindner
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: martinlindner
|
||||
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/matt
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: matt
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/passingby
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: passingby
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/pmario
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: pmario
|
||||
|
||||
|
After Width: | Height: | Size: 577 B |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/poulstaugaard
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: poulstaugaard
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/rouilj
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: rouilj
|
||||
|
||||
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/smandoli
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: smandoli
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,5 @@
|
||||
title: $:/avatars/ubi
|
||||
type: image/jpeg
|
||||
tags: $:/tags/Avatar
|
||||
modifier: ubi
|
||||
|
||||