walkaway-wiki/index.html

3797 lines
7.3 MiB
HTML
Raw Normal View History

<!doctype html>
<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->
<!-- saved from url=(0021)https://tiddlywiki.com -->
2022-04-14 23:41:27 +00:00
<html lang="en-GB">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<!--~~ Raw markup for the top of the head section ~~-->
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
2022-04-14 23:41:27 +00:00
<meta name="tiddlywiki-version" content="5.2.2" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="format-detection" content="telephone=no" />
<meta name="copyright" content="TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
2022-04-14 23:41:27 +00:00
Copyright (c) 2007-2022, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." />
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
2022-04-14 23:41:27 +00:00
<title>KawaiiPunk's Walkaway Wiki
— Punk2Punk
</title>
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
<!--~~ Raw markup ~~-->
</head>
<body class="tc-body">
<!--~~ Raw markup for the top of the body section ~~-->
<!--~~ Static styles ~~-->
<div id="styleArea">
<style data-tiddler-title="$:/boot/boot.css" data-tiddler-type="text/css" type="text/css">/*
Basic styles used before we boot up the parsing engine
*/
/*
Error message and password prompt
*/
.tc-error-form {
font-family: sans-serif;
color: #fff;
z-index: 20000;
position: fixed;
background-color: rgb(255, 75, 75);
border: 8px solid rgb(255, 0, 0);
border-radius: 8px;
width: 50%;
margin-left: 25%;
margin-top: 4em;
padding: 0 2em 1em 2em;
}
.tc-error-form h1 {
text-align: center;
}
.tc-error-prompt {
text-align: center;
color: #000;
}
.tc-error-message {
overflow: auto;
max-height: 40em;
padding-right: 1em;
margin: 1em 0;
white-space: pre-line;
}
.tc-password-wrapper {
font-family: sans-serif;
z-index: 20000;
position: fixed;
text-align: center;
width: 200px;
top: 4em;
left: 50%;
margin-left: -144px; /* - width/2 - paddingHorz/2 - border */
padding: 16px 16px 16px 16px;
border-radius: 8px;
}
.tc-password-wrapper {
color: #000;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: rgb(197, 235, 183);
border: 8px solid rgb(164, 197, 152);
}
.tc-password-wrapper form {
text-align: left;
}
.tc-password-wrapper h1 {
font-size: 16px;
line-height: 20px;
padding-bottom: 16px;
}
.tc-password-wrapper input {
width: 100%;
}
</style>
</div>
<!--~~ Static content for Google and browsers without JavaScript ~~-->
<noscript>
<div id="splashArea">
<p>This <a class="tc-tiddlylink-external" href="https://tiddlywiki.com" rel="noopener noreferrer" target="_blank">TiddlyWiki</a> contains the following tiddlers:</p><p><ul>
2022-04-14 23:41:27 +00:00
<li>$:/build</li>
<li>$:/config/AutoSave</li>
<li>$:/config/DefaultSidebarTab</li>
<li>$:/config/markdown/linkify</li>
<li>$:/config/Navigation/UpdateAddressBar</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-tiddler</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview</li>
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager</li>
<li>$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/blog</li>
<li>$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/help</li>
<li>$:/config/Plugins/Disabled/$:/themes/tiddlywiki/vanilla</li>
<li>$:/config/RelinkOnRename</li>
<li>$:/config/ShowHelp</li>
<li>$:/config/TextEditor/EnableToolbar</li>
<li>$:/config/Tiddlers/TitleLinks</li>
<li>$:/config/Toolbar/ButtonClass</li>
<li>$:/config/Toolbar/Text</li>
<li>$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink</li>
<li>$:/core</li>
<li>$:/DefaultTiddlers</li>
<li>$:/Import</li>
<li>$:/isEncrypted</li>
<li>$:/palette</li>
<li>$:/plugins/tiddlywiki/blog</li>
<li>$:/plugins/tiddlywiki/codemirror-mode-markdown</li>
<li>$:/plugins/tiddlywiki/help</li>
<li>$:/plugins/tiddlywiki/highlight</li>
<li>$:/plugins/tiddlywiki/markdown</li>
<li>$:/SiteSubtitle</li>
<li>$:/SiteTitle</li>
<li>$:/status/IsAnonymous</li>
<li>$:/status/IsLoggedIn</li>
<li>$:/status/IsReadOnly</li>
2022-04-14 23:41:27 +00:00
<li>$:/status/RequireReloadDueToPluginChange</li>
<li>$:/status/UserName</li>
<li>$:/StoryList</li>
<li>$:/temp/info-plugin</li>
<li>$:/theme</li>
<li>$:/themes/tiddlywiki/snowwhite</li>
<li>$:/themes/tiddlywiki/vanilla</li>
<li>$:/themes/tiddlywiki/vanilla/options/sidebarlayout</li>
<li>$:/view</li>
<li>A cheatsheet on discourse</li>
<li>A comparison of cryptographic keycards</li>
<li>A Libertarian Walks Into a Bear: Author Matthew Hongoltz-Hetling on the Free State Project</li>
<li>Abdullah Öcalan On Methodology and the Regime of the Truth</li>
<li>About RSS feed</li>
<li>Acessing Android storage using Termux</li>
<li>Adam Curtis</li>
<li>ADHD and Sleep</li>
<li>ADHD folks on Twitter</li>
<li>Air Quality Monitoring</li>
2021-12-16 12:59:43 +00:00
<li>Airwindows audio plug-ins</li>
<li>Alpkit Gear I have my eye on</li>
<li>Android Encryption</li>
<li>Ant Media Server</li>
<li>Anxiety - Browser based game</li>
<li>Archiving websites onto dat</li>
<li>Autonomous Design Group</li>
<li>Belarus: Anarchists in the Uprising against the Dictatorship</li>
<li>Beyond-the-frontlines-The-building-of-the-democratic-system-in-North-and-East-Syria-Report-Rojava-Information-Center-December-2019-V4.pdf</li>
<li>Bikeshedding</li>
<li>Birds aren't real meme from Chaos Congress</li>
<li>Black Panther Party Programs of Survival</li>
<li>Books</li>
<li>Books To Read</li>
<li>Boosting off-grid resilience</li>
<li>Borg Backup on Android</li>
<li>Borgbackup on Android</li>
<li>Bread Recipes</li>
<li>Broadcasting using autistici.org</li>
<li>Browser Stack</li>
<li>Casio Baby-G BGX-240V-4 Series</li>
<li>CBM 8032 AV computer graphics and sound 2016-2019</li>
<li>ClamAV antivirus on Debian based systems</li>
<li>Community Accountability</li>
<li>Contact tracing</li>
<li>Cool bicycle site</li>
<li>Cool game: A Summers End - Hong Kong 1986</li>
<li>Cool Music</li>
<li>Cool Orgs</li>
<li>Cool phone, laptop hack</li>
<li>Coreboot images for the Thinkpad X230</li>
<li>Cyberpunk Clothing on Etsy</li>
<li>Cycle.travel - Cycle mapping and routing</li>
<li>Cycling trips using Ferries</li>
<li>David Bowie meets Tricky</li>
<li>De-Googling an Android phone</li>
<li>Debian non-free live images</li>
<li>Debian security software</li>
<li>Dervla Murphy</li>
<li>Dialetical Football</li>
<li>Dib's Fitness</li>
<li>DNS rebinding attack</li>
<li>Early Cyberpunk</li>
<li>EARTHEART by YaYa Bones</li>
<li>Ecology</li>
<li>Elite Panic</li>
<li>Enkindle Village School Case Study</li>
<li>Estonia E-Residency and Digital Nomad Visa</li>
<li>Excellent Cycle Mapping site</li>
<li>Exiting The Vampire Castle by Mark Fisher</li>
2022-04-14 22:20:54 +00:00
<li>Fair Ferry</li>
<li>Flash Fiction</li>
<li>Foraging Recipes</li>
<li>From Managerial Feudalism to the Revolt of the Caring Classes</li>
<li>Game Engines</li>
<li>Garden diaries 20.3.20</li>
<li>Garden Diaries 21.3.20</li>
<li>Garden diaries 23.3.20</li>
<li>GDS pre commit - Prevent commiting secrets to git repos</li>
<li>Gideon the Ninth (The Locked Tomb #1)</li>
<li>git-ssb</li>
<li>Glitter + Ashes: Queer Tales of a World That Wouldn't Die</li>
<li>GNOME break timer</li>
<li>GNOME circles</li>
<li>GNOME terminal keyboard shortcuts</li>
<li>Google Pixel 3a Repair Guide</li>
<li>Graphene OS</li>
<li>Great DJ Mixes</li>
<li>Gridsound: DAW in the browser</li>
<li>Habits - Habit tracking</li>
<li>Hackers Curator Fan Site</li>
<li>Half Barges - Canal Boats</li>
<li>HAM Radio Resources</li>
<li>Harrison Consoles VST Plugins</li>
<li>Hello World!</li>
<li>Hosting hypercore sites</li>
<li>How to force the DVLA to accept your name change</li>
<li>How to Use the WP-CLI Command Line Tool to Change Your WordPress Website Url or Domain</li>
<li>In the ruins of the garden (part 1)</li>
<li>Interact with ssh agent using ssh-add</li>
<li>Introduction to AppArmour</li>
<li>Jenny Grahams Around the World Record Breaking Kit</li>
<li>Joining Freenode IRC channels using Matrix</li>
<li>Karl Biscuit</li>
<li>KawaiiPunk</li>
<li>Keyoxide</li>
<li>Khabat Abbas - Journalist in Rojava</li>
<li>Lenovo BIOS Embedded Controller Update Vulnerability</li>
<li>Less Talk Athletics</li>
<li>Libertatia: Pirates and Anarchist Utopia</li>
<li>Libre x42 audio plugins</li>
<li>LibreRouter</li>
<li>Linux / UNIX: DNS Lookup Command</li>
<li>Linux Kernel maintainer's PGP guide</li>
<li>Live Lightning Maps</li>
<li>Logic Mag</li>
<li>London Clarion Cycling Club gear</li>
2022-04-14 23:41:27 +00:00
<li>Los Angeles rideshare drivers union</li>
2022-04-14 23:41:27 +00:00
<li>Marianne Breslauers photos of queer, androgynous and butch women of the 1930s</li>
2022-04-14 23:41:27 +00:00
<li>Matrix Fansite</li>
2022-04-14 23:41:27 +00:00
<li>Meeting check outs</li>
2022-04-14 23:41:27 +00:00
<li>Mixlr</li>
2022-04-14 23:41:27 +00:00
<li>Modified Casio Watches</li>
2022-04-14 23:41:27 +00:00
<li>Motion sensors for home security</li>
2022-04-14 23:41:27 +00:00
<li>Moto G3 iFixit Repair guide</li>
2022-04-14 23:41:27 +00:00
<li>Moxie's Booklist</li>
2022-04-14 23:41:27 +00:00
<li>Mozilla Development Network</li>
2022-04-14 23:41:27 +00:00
<li>Music dump December 2020</li>
2022-04-14 23:41:27 +00:00
<li>Music Theory Explorer</li>
2022-04-14 23:41:27 +00:00
<li>New Cory Doctorow book "Attack Surface"</li>
2022-04-14 23:41:27 +00:00
<li>New Medicinal Herb Colouring Book from Solidarity Apothercary</li>
2022-04-14 23:41:27 +00:00
<li>New Tiddler</li>
2022-04-14 23:41:27 +00:00
<li>NewPipe YouTube app front-end</li>
2022-04-14 23:41:27 +00:00
<li>Nitro key</li>
2022-04-14 23:41:27 +00:00
<li>No dig gardening</li>
2022-04-14 23:41:27 +00:00
<li>NODE zine</li>
2022-04-14 23:41:27 +00:00
<li>Novation Launchpad Bitwig Studio Scripts</li>
2022-04-14 23:41:27 +00:00
<li>On opening random pdf files</li>
2022-04-14 23:41:27 +00:00
<li>On Productivity</li>
2022-04-14 23:41:27 +00:00
<li>Online map for political demonstrations</li>
2022-04-14 23:41:27 +00:00
<li>OpenWRT on BT Home Hub 5A</li>
2022-04-14 23:41:27 +00:00
<li>Opis Retro Phones</li>
2022-04-14 23:41:27 +00:00
<li>OSSEC Host Intrusion Detection System</li>
2022-04-14 23:41:27 +00:00
<li>Owncast</li>
2022-04-14 23:41:27 +00:00
<li>PA System For a Soundsystem Co-op</li>
2022-04-14 23:41:27 +00:00
<li>Panic Button</li>
2022-04-14 23:41:27 +00:00
<li>Patterns for a decentralised society</li>
2022-04-14 23:41:27 +00:00
<li>Paul Oakenfold Goa Mix 1994</li>
2022-04-14 23:41:27 +00:00
<li>Permaculture Link Dump</li>
2022-04-14 23:41:27 +00:00
<li>Photographing Wars in the Middle East</li>
2022-04-14 23:41:27 +00:00
<li>Pinephone</li>
2022-04-14 23:41:27 +00:00
<li>Possessor review Brandon Cronenberg's terrifying sci-fi horror freak-out</li>
2022-04-14 23:41:27 +00:00
<li>Privacy respecting DNS service</li>
2022-04-14 23:41:27 +00:00
<li>Push to Talk: Online mini Chaos Congress</li>
2022-04-14 23:41:27 +00:00
<li>Queer Solarpunk Blog Post</li>
2022-04-14 23:41:27 +00:00
<li>Qwant Open Street Maps frontend</li>
2022-04-14 23:41:27 +00:00
<li>Raspberry Pi as home network monitor</li>
2022-04-14 23:41:27 +00:00
<li>Recipes</li>
2022-04-14 23:41:27 +00:00
<li>Relationship Anarchy</li>
2022-04-14 23:41:27 +00:00
<li>Remove Unused Flatpak Runtimes</li>
2022-04-14 23:41:27 +00:00
<li>Reverb pre delay calculator</li>
2022-04-14 23:41:27 +00:00
<li>RSS feed for Mastodon and Pixelfed accounts</li>
2022-04-14 23:41:27 +00:00
<li>Rural Co-ops</li>
2022-04-14 23:41:27 +00:00
<li>Sad Cookbook - Simple recipes for sad times</li>
2022-04-14 23:41:27 +00:00
<li>Sarah Brightman - I Lost My Heart to a Starship Trooper</li>
2022-04-14 23:41:27 +00:00
<li>Scuttlebot written in C</li>
2022-04-14 23:41:27 +00:00
<li>Seat 61</li>
2022-04-14 23:41:27 +00:00
<li>Security for the savvy leftist, Part 1: OpSec</li>
2022-04-14 23:41:27 +00:00
<li>Security Monitoring Software</li>
2022-04-14 23:41:27 +00:00
<li>seedvault - encrypted Android backups</li>
2022-04-14 23:41:27 +00:00
<li>Setting snap package auto upgrade frequency</li>
2022-04-14 23:41:27 +00:00
<li>Sgian-dubh (Dirk) knife</li>
2022-04-14 23:41:27 +00:00
<li>Shoes</li>
2022-04-14 23:41:27 +00:00
<li>Signal Voice Call Echo Problems</li>
2022-04-14 23:41:27 +00:00
<li>Siren Moon Illustrations</li>
2022-04-14 23:41:27 +00:00
<li>Skills for Revolutionary Survival: 1. Trauma Medical Gear</li>
2022-04-14 23:41:27 +00:00
<li>Slax - Live USB distro</li>
2022-04-14 23:41:27 +00:00
<li>Slow news in a fast world</li>
2022-04-14 23:41:27 +00:00
<li>Solarpower</li>
2022-04-14 23:41:27 +00:00
<li>Solarpunk: To walkaway or to stay and fight?</li>
2022-04-14 23:41:27 +00:00
<li>SSB-Room</li>
2022-04-14 23:41:27 +00:00
<li>Starship: cross shell prompt written in rust</li>
2022-04-14 23:41:27 +00:00
<li>Stopping phishing campaigns with bash</li>
2022-04-14 23:41:27 +00:00
<li>Storyville: Pepe The Frog</li>
2022-04-14 23:41:27 +00:00
<li>Sunbeam.City in danger</li>
2022-04-14 23:41:27 +00:00
<li>Tech</li>
2022-04-14 23:41:27 +00:00
<li>Tekmîl: Creating a Culture of Constructive Criticism</li>
2022-04-14 23:41:27 +00:00
<li>The Commoner</li>
2022-04-14 23:41:27 +00:00
<li>The Dinghy Cruising Companion: Tales and Advice from Sailing a Small Open Boat</li>
2022-04-14 23:41:27 +00:00
<li>The Last Clarion House</li>
2022-04-14 23:41:27 +00:00
<li>The Megalithic Portal</li>
2022-04-14 23:41:27 +00:00
<li>The Racial Bias Built Into Photography</li>
2022-04-14 23:41:27 +00:00
<li>The Reasonable Person's Guide To Prepping</li>
2022-04-14 23:41:27 +00:00
<li>The Scuttlebutt Song</li>
2022-04-14 23:41:27 +00:00
<li>TiddlyWiki Markdown Plugin</li>
2022-04-14 23:41:27 +00:00
<li>TiddlyWiki Readme</li>
2022-04-14 23:41:27 +00:00
<li>TiddlyWiki RSS/Atom feed</li>
2022-04-14 23:41:27 +00:00
<li>TiddlyWiki5 RSS Feed Plugin</li>
2022-04-14 23:41:27 +00:00
<li>Tunes April 2021</li>
2022-04-14 23:41:27 +00:00
<li>Tunes March 2021</li>
2022-04-14 23:41:27 +00:00
<li>UK Ham Radio Course Materials</li>
2022-04-14 23:41:27 +00:00
<li>Unemployed Workers Centres</li>
2022-04-14 23:41:27 +00:00
<li>Untitled</li>
2022-04-14 23:41:27 +00:00
<li>Untitled 1</li>
2022-04-14 23:41:27 +00:00
<li>Update all packages using opkg on OpenWRT</li>
2022-04-14 23:41:27 +00:00
<li>Usability Testing (UX)</li>
2022-04-14 23:41:27 +00:00
<li>Web Image Scrubber</li>
2022-04-14 23:41:27 +00:00
<li>Welcome to my blog!</li>
2022-04-14 23:41:27 +00:00
<li>What I'm listening to December 2020</li>
2022-04-14 23:41:27 +00:00
<li>What Is De-essing? The Dos and Donts of Using a De-esser</li>
2022-04-14 23:41:27 +00:00
<li>Whats App terms of service change</li>
2022-04-14 23:41:27 +00:00
<li>WhatsApp Vulnrebility April 2021</li>
2022-04-14 23:41:27 +00:00
<li>Where to get camping gear in UK</li>
2022-04-14 23:41:27 +00:00
<li>Wild Food UK</li>
2022-04-14 23:41:27 +00:00
<li>Wordpress Crowdfunding Plugin</li>
2022-04-14 23:41:27 +00:00
<li>Z-TRITON Solarpunk Bike/Boat/Home</li>
2022-04-14 23:41:27 +00:00
<li>Zines! Zines! Zines!</li>
2022-04-14 23:41:27 +00:00
<li>Zoom MS-70CDR Multi-Effects Pedal</li>
2022-04-14 23:41:27 +00:00
</ul>
</p>
2022-04-14 23:41:27 +00:00
<style>
.tc-remove-when-wiki-loaded {display: none;}
</style>
2022-04-14 23:41:27 +00:00
</div>
</noscript>
<!--~~ Ordinary tiddlers ~~-->
<script class="tiddlywiki-tiddler-store" type="application/json">[
{"title":"$:/build","commit":"6c505ebc49b8d95953aa4df66577b2df626a78ea","text":"Built from branch 'tiddlywiki-com' at commit 6c505ebc49b8d95953aa4df66577b2df626a78ea of https://github.com/Jermolene/TiddlyWiki5 at 2022-04-12 11:09:40 UTC\n"},
{"title":"$:/config/AutoSave","text":"no","created":"20200326203112365","modified":"20200327162207162"},
{"title":"$:/config/DefaultSidebarTab","text":"$:/core/ui/SideBar/Recent","created":"20200312224733796","modified":"20200312224733796"},
{"title":"$:/config/markdown/linkify","text":"true","created":"20200421000903951","modified":"20200421000906555"},
{"title":"$:/config/Navigation/UpdateAddressBar","text":"permalink","created":"20200312224754656","modified":"20200312225039624"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page","type":"text/vnd.tiddlywiki","text":"hide","bag":"default","created":"20200227001837041","modified":"20200308000108844","revision":"0"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home","text":"show","created":"20200307153344042","modified":"20200324114212774"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import","type":"text/vnd.tiddlywiki","text":"show","bag":"default","created":"20200227001826618","modified":"20200227001827707","revision":"0"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal","text":"show","created":"20200306190149187","modified":"20200306190149187"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-tiddler","text":"hide","created":"20200324114120055","modified":"20200324114120055"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview","text":"hide","created":"20200307171229389","modified":"20200308000055294"},
{"title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager","text":"hide","created":"20200321184948007","modified":"20200321231201289"},
{"title":"$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/blog","text":"yes","created":"20200324113644450","modified":"20200324113644451"},
{"title":"$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/help","text":"yes","created":"20200324111554083","modified":"20200324111554083"},
{"title":"$:/config/Plugins/Disabled/$:/themes/tiddlywiki/vanilla","type":"text/vnd.tiddlywiki","text":"no","bag":"default","created":"20200226234048960","modified":"20200226234051250","revision":"0"},
{"title":"$:/config/RelinkOnRename","text":"yes","created":"20200307230127455","modified":"20200307230127455"},
{"title":"$:/config/ShowHelp","text":"no","created":"20200324111540145","modified":"20200324111547039"},
{"title":"$:/config/TextEditor/EnableToolbar","text":"yes","created":"20200324011720512","modified":"20200324011722110"},
{"title":"$:/config/Tiddlers/TitleLinks","text":"yes","created":"20200312004526806","modified":"20200312004526806"},
{"title":"$:/config/Toolbar/ButtonClass","text":"tc-btn-invisible","created":"20200312004535838","modified":"20200312004550385"},
{"title":"$:/config/Toolbar/Text","text":"no","created":"20200312004600147","modified":"20200312004611410"},
{"title":"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink","type":"text/vnd.tiddlywiki","text":"hide","bag":"default","created":"20200227001747952","modified":"20200227001756647","revision":"0"},
{"title":"$:/core","name":"Core","description":"TiddlyWiki5 core","author":"JeremyRuston","core-version":">=5.0.0","plugin-priority":"0","list":"readme","version":"5.2.2","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/Acknowledgements\":{\"title\":\"$:/Acknowledgements\",\"text\":\"TiddlyWiki incorporates code from these fine OpenSource projects:\\n\\n* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]\\n* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]\\n* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]\\n\\nAnd media from these projects:\\n\\n* World flag icons from [[Wikipedia|http://commons.wikimedia.org/wiki/Category:SVG_flags_by_country]]\\n\"},\"$:/core/copyright.txt\":{\"title\":\"$:/core/copyright.txt\",\"type\":\"text/plain\",\"text\":\"TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)\\n\\nCopyright (c) 2004-2007, Jeremy Ruston\\nCopyright (c) 2007-2022, UnaMesa Association\\nAll rights reserved.\\n\\nRedistribution and use in source and binary forms, with or without\\nmodification, are permitted provided that the following conditions are met:\\n\\n* Redistributions of source code must retain the above copyright notice, this\\n list of conditions and the following disclaimer.\\n\\n* Redistributions in binary form must reproduce the above copyright notice,\\n this list of conditions and the following disclaimer in the documentation\\n and/or other materials provided with the distribution.\\n\\n* Neither the name of the copyright holder nor the names of its\\n contributors may be used to endorse or promote products derived from\\n this software without specific prior written permission.\\n\\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'\\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\"},\"$:/core/icon\":{\"title\":\"$:/core/icon\",\"tags\":\"$:/tags/Image\",\"text\":\"\u003Csvg width=\\\"22pt\\\" height=\\\"22pt\\\" viewBox=\\\"0 0 128 128\\\">\u003Cpath d=\\\"M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 15.594 1.114 1.94 4.226 2.652 3.02 4.406-.3
{"title":"$:/DefaultTiddlers","text":"[list[$:/StoryList]]","created":"20200227010321655","modified":"20200227010323152"},
{"title":"$:/Import","text":"The following tiddlers were imported:\n\n# [[$:/config/AutoSave]]\n# [[$:/config/DefaultSidebarTab]]\n# [[$:/config/markdown/linkify]]\n# [[$:/config/Navigation/UpdateAddressBar]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-tiddler]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview]]\n# [[$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager]]\n# [[$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/blog]]\n# [[$:/config/Plugins/Disabled/$:/plugins/tiddlywiki/help]]\n# [[$:/config/Plugins/Disabled/$:/themes/tiddlywiki/vanilla]]\n# [[$:/config/RelinkOnRename]]\n# [[$:/config/ShowHelp]]\n# [[$:/config/TextEditor/EnableToolbar]]\n# [[$:/config/Tiddlers/TitleLinks]]\n# [[$:/config/Toolbar/ButtonClass]]\n# [[$:/config/Toolbar/Text]]\n# [[$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink]]\n# [[$:/DefaultTiddlers]]\n# [[$:/isEncrypted]]\n# [[$:/palette]]\n# [[$:/plugins/tiddlywiki/blog]]\n# [[$:/plugins/tiddlywiki/codemirror-mode-markdown]]\n# [[$:/plugins/tiddlywiki/help]]\n# [[$:/plugins/tiddlywiki/highlight]]\n# [[$:/plugins/tiddlywiki/markdown]]\n# [[$:/SiteSubtitle]]\n# [[$:/SiteTitle]]\n# [[$:/status/IsAnonymous]]\n# [[$:/status/IsLoggedIn]]\n# [[$:/status/IsReadOnly]]\n# [[$:/status/UserName]]\n# [[$:/theme]]\n# [[$:/themes/tiddlywiki/snowwhite]]\n# [[$:/themes/tiddlywiki/vanilla]]\n# [[$:/themes/tiddlywiki/vanilla/options/sidebarlayout]]\n# [[$:/view]]\n# [[A cheatsheet on discourse]]\n# [[A comparison of cryptographic keycards]]\n# [[A Libertarian Walks Into a Bear: Author Matthew Hongoltz-Hetling on the Free State Project]]\n# [[Abdullah Öcalan On Methodology and the Regime of the Truth]]\n# [[About RSS feed]]\n# [[Acessing Android storage using Termux]]\n# [[Adam Curtis]]\n# [[ADHD and Sleep]]\n# [[ADHD folks on Twitter]]\n# [[Air Quality Monitoring]]\n# [[Airwindows audio plug-ins]]\n# [[Alpkit Gear I have my eye on]]\n# [[Android Encryption]]\n# [[Ant Media Server]]\n# [[Anxiety - Browser based game]]\n# [[Archiving websites onto dat]]\n# [[Autonomous Design Group]]\n# [[Belarus: Anarchists in the Uprising against the Dictatorship]]\n# [[Beyond-the-frontlines-The-building-of-the-democratic-system-in-North-and-East-Syria-Report-Rojava-Information-Center-December-2019-V4.pdf]]\n# [[Bikeshedding]]\n# [[Birds aren't real meme from Chaos Congress]]\n# [[Black Panther Party Programs of Survival]]\n# [[Books]]\n# [[Books To Read]]\n# [[Boosting off-grid resilience]]\n# [[Borg Backup on Android]]\n# [[Borgbackup on Android]]\n# [[Bread Recipes]]\n# [[Broadcasting using autistici.org]]\n# [[Browser Stack]]\n# [[Casio Baby-G BGX-240V-4 Series]]\n# [[CBM 8032 AV computer graphics and sound 2016-2019]]\n# [[ClamAV antivirus on Debian based systems]]\n# [[Community Accountability]]\n# [[Contact tracing]]\n# [[Cool bicycle site]]\n# [[Cool game: A Summers End - Hong Kong 1986]]\n# [[Cool Music]]\n# [[Cool Orgs]]\n# [[Cool phone, laptop hack]]\n# [[Coreboot images for the Thinkpad X230]]\n# [[Cyberpunk Clothing on Etsy]]\n# [[Cycle.travel - Cycle mapping and routing]]\n# [[Cycling trips using Ferries]]\n# [[David Bowie meets Tricky]]\n# [[De-Googling an Android phone]]\n# [[Debian non-free live images]]\n# [[Debian security software]]\n# [[Dervla Murphy]]\n# [[Dialetical Football]]\n# [[Dib's Fitness]]\n# [[DNS rebinding attack]]\n# [[Early Cyberpunk]]\n# [[EARTHEART by YaYa Bones]]\n# [[Ecology]]\n# [[Elite Panic]]\n# [[Enkindle Village School Case Study]]\n# [[Estonia E-Residency and Digital Nomad Visa]]\n# [[Excellent Cycle Mapping site]]\n# [[Exiting The Vampire Castle by Mark Fisher]]\n# [[Fair Ferry]]\n# [[Flash Fiction]]\n# [[Foraging Recipes]]\n# [[From Managerial Feudalism to the Revolt of the Caring Classes
{"title":"$:/isEncrypted","text":"no","bag":"default","revision":"0"},
{"title":"$:/palette","text":"$:/palettes/Blue","created":"20200307153400695","modified":"20200308010225751"},
{"title":"$:/plugins/tiddlywiki/blog","name":"Blog","description":"Blog publishing tools","list":"readme docs","version":"5.2.2","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/plugins/tiddlywiki/blog/docs\":{\"title\":\"$:/plugins/tiddlywiki/blog/docs\",\"text\":\"Until there's more documentation, see an example of the use of this plugin here:\\n\\n* Blog: http://jermolene-blog.github.io/\\n* Repository: https://github.com/Jermolene-blog/blog\\n\"},\"$:/plugins/tiddlywiki/blog/readme\":{\"title\":\"$:/plugins/tiddlywiki/blog/readme\",\"text\":\"This plugin contains tools to help publish blogs:\\n\\n* Templates and tools for building static HTML pages and posts\\n\"},\"$:/plugins/tiddlywiki/blog/templates/html-page/page\":{\"title\":\"$:/plugins/tiddlywiki/blog/templates/html-page/page\",\"text\":\"\\\\define tv-wikilink-template() posts/$uri_doubleencoded$.html\\n\\\\define tv-config-toolbar-icons() no\\n\\\\define tv-config-toolbar-text() no\\n\\\\define tv-config-toolbar-class() tc-btn-invisible\\n`\u003C!doctype html>\\n\u003Chtml>\\n\u003Chead>\\n\u003Cmeta http-equiv=\\\"Content-Type\\\" content=\\\"text/html;charset=utf-8\\\" />\\n\u003Cmeta name=\\\"generator\\\" content=\\\"TiddlyWiki\\\" />\\n\u003Cmeta name=\\\"tiddlywiki-version\\\" content=\\\"`{{$:/core/templates/version}}`\\\" />\\n\u003Cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\" />\\n\u003Cmeta name=\\\"apple-mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\u003Cmeta name=\\\"apple-mobile-web-app-status-bar-style\\\" content=\\\"black-translucent\\\" />\\n\u003Cmeta name=\\\"mobile-web-app-capable\\\" content=\\\"yes\\\"/>\\n\u003Cmeta name=\\\"format-detection\\\" content=\\\"telephone=no\\\">\\n\u003Clink id=\\\"faviconLink\\\" rel=\\\"shortcut icon\\\" href=\\\"favicon.ico\\\">\\n\u003Clink rel=\\\"stylesheet\\\" href=\\\"static.css\\\">\\n\u003Ctitle>`\u003C$transclude field=\\\"caption\\\">\u003C$view field=\\\"title\\\"/>\u003C/$transclude>: {{$:/core/wiki/title}}`\u003C/title>\\n\u003C/head>\\n\u003Cbody class=\\\"tc-body\\\">\\n`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`\\n\u003Csection class=\\\"tc-story-river\\\">\\n`\u003C$importvariables filter=\\\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\\\">\\n\u003C$view tiddler=\\\"$:/plugins/tiddlywiki/blog/templates/tiddler\\\" format=\\\"htmlwikified\\\"/>\\n\u003C/$importvariables>`\\n\u003C/section>\\n\u003C/body>\\n\u003C/html>\\n`\\n\"},\"$:/plugins/tiddlywiki/blog/templates/html-page/post\":{\"title\":\"$:/plugins/tiddlywiki/blog/templates/html-page/post\",\"text\":\"\\\\define tv-wikilink-template() /$uri_doubleencoded$.html\\n\\\\define tv-config-toolbar-icons() no\\n\\\\define tv-config-toolbar-text() no\\n\\\\define tv-config-toolbar-class() tc-btn-invisible\\n`\u003C!doctype html>\\n\u003Chtml>\\n\u003Chead>\\n\u003Cmeta http-equiv=\\\"Content-Type\\\" content=\\\"text/html;charset=utf-8\\\" />\\n\u003Cmeta name=\\\"generator\\\" content=\\\"TiddlyWiki\\\" />\\n\u003Cmeta name=\\\"tiddlywiki-version\\\" content=\\\"`{{$:/core/templates/version}}`\\\" />\\n\u003Cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\" />\\n\u003Cmeta name=\\\"apple-mobile-web-app-capable\\\" content=\\\"yes\\\" />\\n\u003Cmeta name=\\\"apple-mobile-web-app-status-bar-style\\\" content=\\\"black-translucent\\\" />\\n\u003Cmeta name=\\\"mobile-web-app-capable\\\" content=\\\"yes\\\"/>\\n\u003Cmeta name=\\\"format-detection\\\" content=\\\"telephone=no\\\">\\n\u003Clink id=\\\"faviconLink\\\" rel=\\\"shortcut icon\\\" href=\\\"../favicon.ico\\\">\\n\u003Clink rel=\\\"stylesheet\\\" href=\\\"../static.css\\\">\\n\u003Ctitle>`\u003C$transclude field=\\\"caption\\\">\u003C$view field=\\\"title\\\"/>\u003C/$transclude>: {{$:/core/wiki/title}}`\u003C/title>\\n\u003C/head>\\n\u003Cbody class=\\\"tc-body\\\">\\n`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`\\n\u003Csection class=\\\"tc-story-river\\\">\\n`\u003C$importvariables filter=\\\"[[$:/core/ui/Pa
{"title":"$:/plugins/tiddlywiki/codemirror-mode-markdown","name":"CodeMirror Mode Markdown","description":"Markdown highlighting mode for CodeMirror","parent-plugin":"$:/plugins/tiddlywiki/codemirror","dependents":"$:/plugins/tiddlywiki/codemirror-mode-xml","list":"readme","version":"5.2.2","plugin-type":"plugin","type":"application/json","text":"{\"tiddlers\":{\"$:/plugins/tiddlywiki/codemirror/mode/markdown/markdown.js\":{\"text\":\"// CodeMirror, copyright (c) by Marijn Haverbeke and others\\n// Distributed under an MIT license: https://codemirror.net/LICENSE\\n!function(t){\\\"object\\\"==typeof exports&&\\\"object\\\"==typeof module?t(require(\\\"../../lib/codemirror\\\"),require(\\\"../xml/xml\\\"),require(\\\"../tw-meta\\\")):\\\"function\\\"==typeof define&&define.amd?define([\\\"../../lib/codemirror\\\",\\\"../xml/xml\\\",\\\"../tw-meta\\\"],t):t(CodeMirror)}(function(j){\\\"use strict\\\";j.defineMode(\\\"markdown\\\",function(c,x){var A=j.getMode(c,\\\"text/html\\\"),u=\\\"null\\\"==A.name;void 0===x.highlightFormatting&&(x.highlightFormatting=!1),void 0===x.maxBlockquoteDepth&&(x.maxBlockquoteDepth=0),void 0===x.taskLists&&(x.taskLists=!1),void 0===x.strikethrough&&(x.strikethrough=!1),void 0===x.emoji&&(x.emoji=!1),void 0===x.fencedCodeBlockHighlighting&&(x.fencedCodeBlockHighlighting=!0),void 0===x.fencedCodeBlockDefaultMode&&(x.fencedCodeBlockDefaultMode=\\\"text/plain\\\"),void 0===x.xml&&(x.xml=!0),void 0===x.tokenTypeOverrides&&(x.tokenTypeOverrides={});var C={header:\\\"header\\\",code:\\\"comment\\\",quote:\\\"quote\\\",list1:\\\"variable-2\\\",list2:\\\"variable-3\\\",list3:\\\"keyword\\\",hr:\\\"hr\\\",image:\\\"image\\\",imageAltText:\\\"image-alt-text\\\",imageMarker:\\\"image-marker\\\",formatting:\\\"formatting\\\",linkInline:\\\"link\\\",linkEmail:\\\"link\\\",linkText:\\\"link\\\",linkHref:\\\"string\\\",em:\\\"em\\\",strong:\\\"strong\\\",strikethrough:\\\"strikethrough\\\",emoji:\\\"builtin\\\"};for(var t in C)C.hasOwnProperty(t)&&x.tokenTypeOverrides[t]&&(C[t]=x.tokenTypeOverrides[t]);var f=/^([*\\\\-_])(?:\\\\s*\\\\1){2,}\\\\s*$/,k=/^(?:[*\\\\-+]|^[0-9]+([.)]))\\\\s+/,S=/^\\\\[(x| )\\\\](?=\\\\s)/i,F=x.allowAtxHeaderWithoutSpace?/^(#+)/:/^(#+)(?: |$)/,D=/^ {0,3}(?:\\\\={1,}|-{2,})\\\\s*$/,i=/^[^#!\\\\[\\\\]*_\\\\\\\\\u003C>` \\\"'(~:]+/,p=/^(~~~+|```+)[ \\\\t]*([\\\\w\\\\/+#-]*)[^\\\\n`]*$/,E=/^\\\\s*\\\\[[^\\\\]]+?\\\\]:.*$/,v=/[!\\\"#$%&'()*+,\\\\-.\\\\/:;\u003C=>?@\\\\[\\\\\\\\\\\\]^_`{|}~\\\\xA1\\\\xA7\\\\xAB\\\\xB6\\\\xB7\\\\xBB\\\\xBF\\\\u037E\\\\u0387\\\\u055A-\\\\u055F\\\\u0589\\\\u058A\\\\u05BE\\\\u05C0\\\\u05C3\\\\u05C6\\\\u05F3\\\\u05F4\\\\u0609\\\\u060A\\\\u060C\\\\u060D\\\\u061B\\\\u061E\\\\u061F\\\\u066A-\\\\u066D\\\\u06D4\\\\u0700-\\\\u070D\\\\u07F7-\\\\u07F9\\\\u0830-\\\\u083E\\\\u085E\\\\u0964\\\\u0965\\\\u0970\\\\u0AF0\\\\u0DF4\\\\u0E4F\\\\u0E5A\\\\u0E5B\\\\u0F04-\\\\u0F12\\\\u0F14\\\\u0F3A-\\\\u0F3D\\\\u0F85\\\\u0FD0-\\\\u0FD4\\\\u0FD9\\\\u0FDA\\\\u104A-\\\\u104F\\\\u10FB\\\\u1360-\\\\u1368\\\\u1400\\\\u166D\\\\u166E\\\\u169B\\\\u169C\\\\u16EB-\\\\u16ED\\\\u1735\\\\u1736\\\\u17D4-\\\\u17D6\\\\u17D8-\\\\u17DA\\\\u1800-\\\\u180A\\\\u1944\\\\u1945\\\\u1A1E\\\\u1A1F\\\\u1AA0-\\\\u1AA6\\\\u1AA8-\\\\u1AAD\\\\u1B5A-\\\\u1B60\\\\u1BFC-\\\\u1BFF\\\\u1C3B-\\\\u1C3F\\\\u1C7E\\\\u1C7F\\\\u1CC0-\\\\u1CC7\\\\u1CD3\\\\u2010-\\\\u2027\\\\u2030-\\\\u2043\\\\u2045-\\\\u2051\\\\u2053-\\\\u205E\\\\u207D\\\\u207E\\\\u208D\\\\u208E\\\\u2308-\\\\u230B\\\\u2329\\\\u232A\\\\u2768-\\\\u2775\\\\u27C5\\\\u27C6\\\\u27E6-\\\\u27EF\\\\u2983-\\\\u2998\\\\u29D8-\\\\u29DB\\\\u29FC\\\\u29FD\\\\u2CF9-\\\\u2CFC\\\\u2CFE\\\\u2CFF\\\\u2D70\\\\u2E00-\\\\u2E2E\\\\u2E30-\\\\u2E42\\\\u3001-\\\\u3003\\\\u3008-\\\\u3011\\\\u3014-\\\\u301F\\\\u3030\\\\u303D\\\\u30A0\\\\u30FB\\\\uA4FE\\\\uA4FF\\\\uA60D-\\\\uA60F\\\\uA673\\\\uA67E\\\\uA6F2-\\\\uA6F7\\\\uA874-\\\\uA877\\\\uA8CE\\\\uA8CF\\\\uA8F8-\\\\uA8FA\\\\uA8FC\\\\uA92E\\\\uA92F\\\\uA95F\\\\uA9C1-\\\\uA9CD\\\\uA9DE\\\\uA9DF\\\\uAA5C-\\\\uAA5F\\\\uAADE\\\\uAADF\\\\uAAF0\\\\uAAF1\\\\uABEB\\\\uFD3E\\\\uFD3F\\\\uFE10-\\\\uFE19\\\\uFE30-\\\\uFE52\\\\uFE54-\\\\uFE61\\\\u
{"title":"$:/plugins/tiddlywiki/help","name":"Help","description":"Floating help panel","list":"readme","version":"5.2.2","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/plugins/tiddlywiki/help/HelpPanel\":{\"title\":\"$:/plugins/tiddlywiki/help/HelpPanel\",\"tags\":\"$:/tags/PageTemplate\",\"text\":\"\u003C$reveal type=\\\"match\\\" state=\\\"$:/config/ShowHelp\\\" text=\\\"yes\\\">\\n\u003Cdiv class=\\\"tc-help-panel\\\">\\n\u003Cdiv class=\\\"tc-tiddler-controls\\\">\\n\u003C$button set=\\\"$:/config/ShowHelp\\\" setTo=\\\"no\\\" class=\\\"tc-btn-invisible\\\">{{$:/core/images/close-button}}\u003C/$button> ''Help Panel''\\n\u003C/div>\\n\u003C\u003Ctabs \\\"[all[shadows+tiddlers]tag[$:/tags/HelpPanel]!has[draft.of]]\\\" \\\"$:/plugins/tiddlywiki/help/HelpPanel/Support\\\" \\\"$:/state/tab/help\\\">>\\n\u003C/div>\\n\u003C/$reveal>\\n\\n\"},\"$:/config/Help/CurrentVideo\":{\"title\":\"$:/config/Help/CurrentVideo\",\"text\":\"$:/plugins/tiddlywiki/help/Videos/Introduction\"},\"$:/config/ShowHelp\":{\"title\":\"$:/config/ShowHelp\",\"text\":\"no\"},\"$:/plugins/help/Buttons/help\":{\"title\":\"$:/plugins/help/Buttons/help\",\"tags\":\"$:/tags/PageControls\",\"caption\":\"{{$:/core/images/help}} {{$:/language/Buttons/Help/Caption}}\",\"description\":\"{{$:/language/Buttons/Help/Hint}}\",\"text\":\"\\\\whitespace trim\\n\\\\define help-inner()\\n\\\\whitespace trim\\n\u003C$list filter=\\\"[[$:/config/ShowHelp]get[text]] +[else[no]match[yes]]\\\" variable=\\\"ignore\\\">\\n\u003C$button set=\\\"$:/config/ShowHelp\\\" setTo=\\\"no\\\" tooltip={{$:/language/Buttons/Help/Hint}} aria-label={{$:/language/Buttons/Help/Caption}} class=\\\"\\\"\\\"$(tv-config-toolbar-class)$ tc-selected\\\"\\\"\\\">\\n\u003C$list filter=\\\"[\u003Ctv-config-toolbar-icons>match[yes]]\\\">\\n{{$:/core/images/help}}\\n\u003C/$list>\\n\u003C$list filter=\\\"[\u003Ctv-config-toolbar-text>match[yes]]\\\">\\n\u003Cspan class=\\\"tc-btn-text\\\">\u003C$text text={{$:/language/Buttons/Help/Caption}}/>\u003C/span>\\n\u003C/$list>\\n\u003C/$button>\\n\u003C/$list>\\n\u003C$list filter=\\\"[[$:/config/ShowHelp]get[text]] +[else[no]!match[yes]]\\\" variable=\\\"ignore\\\">\\n\u003C$button set=\\\"$:/config/ShowHelp\\\" setTo=\\\"yes\\\" tooltip={{$:/language/Buttons/Help/Hint}} aria-label={{$:/language/Buttons/Help/Caption}} class=\u003C\u003Ctv-config-toolbar-class>>>\\n\u003C$list filter=\\\"[\u003Ctv-config-toolbar-icons>match[yes]]\\\">\\n{{$:/core/images/help}}\\n\u003C/$list>\\n\u003C$list filter=\\\"[\u003Ctv-config-toolbar-text>match[yes]]\\\">\\n\u003Cspan class=\\\"tc-btn-text\\\">\u003C$text text={{$:/language/Buttons/Help/Caption}}/>\u003C/span>\\n\u003C/$list>\\n\u003C/$button>\\n\u003C/$list>\\n\\\\end\\n\u003C\u003Chelp-inner>>\\n\"},\"$:/plugins/tiddlywiki/help/readme\":{\"title\":\"$:/plugins/tiddlywiki/help/readme\",\"text\":\"This plugin provides an overlay help panel at the bottom right of the window.\\n\\n[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/help]]\\n\"},\"$:/plugins/tiddlywiki/help/styles\":{\"title\":\"$:/plugins/tiddlywiki/help/styles\",\"tags\":\"[[$:/tags/Stylesheet]]\",\"text\":\"\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\n.tc-help-panel {\\n\\tposition: fixed;\\n\\tbottom: 0;\\n\\tright: 0;\\n\\twidth: 310px;\\n\\theight: 400px;\\n\\toverflow: auto;\\n\\t-webkit-overflow-scrolling: touch;\\n\\t\u003C\u003Cbox-shadow \\\"0px 0px 5px rgba(0, 0, 0, 0.3)\\\">>\\n\\tborder: 1px solid \u003C\u003Ccolour tiddler-border>>;\\n\\tbackground: \u003C\u003Ccolour tiddler-background>>;\\n\\tpadding: 1em;\\n\\tmargin: 0.5em;\\n\\tz-index: 1000;\\n}\\n\\ndl.tc-help-cheatsheet {\\n\\toverflow: hidden;\\n}\\n\\ndl.tc-help-cheatsheet .red {\\n\\tcolor: red;\\n}\\n\\n.tc-help-cheatsheet > dt {\\n\\tdisplay: block;\\n\\tfloat: left;\\n\\tclear: left;\\n\\tmargin: 2% 1em 0 0;\\n\\tpadding;\\n\\tfont-weight: normal;\\n\\twidth: 45%;\\n}\\n\\n.tc-help-cheatsheet > dt > pre {\\n\\tmargin: 0;\\n}\\n\\n.tc-help-cheatsheet >
{"title":"$:/plugins/tiddlywiki/highlight","name":"Highlight","description":"Highlight.js syntax highlighting","author":"Joao Bolila","list":"readme usage license","version":"5.2.2","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/config/HighlightPlugin/TypeMappings/application/javascript\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/application/javascript\",\"text\":\"javascript\"},\"$:/config/HighlightPlugin/TypeMappings/application/json\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/application/json\",\"text\":\"json\"},\"$:/config/HighlightPlugin/TypeMappings/text/css\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/text/css\",\"text\":\"css\"},\"$:/config/HighlightPlugin/TypeMappings/text/html\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/text/html\",\"text\":\"html\"},\"$:/config/HighlightPlugin/TypeMappings/image/svg+xml\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/image/svg+xml\",\"text\":\"xml\"},\"$:/config/HighlightPlugin/TypeMappings/text/x-markdown\":{\"title\":\"$:/config/HighlightPlugin/TypeMappings/text/x-markdown\",\"text\":\"markdown\"},\"$:/plugins/tiddlywiki/highlight/highlight.js\":{\"text\":\"var hljs = require(\\\"$:/plugins/tiddlywiki/highlight/highlight.js\\\");\\n/*!\\n Highlight.js v11.4.0 (git: 2d0e7c1094)\\n (c) 2006-2022 Ivan Sagalaev and other contributors\\n License: BSD-3-Clause\\n */\\nvar hljs=function(){\\\"use strict\\\";var e={exports:{}};function t(e){\\nreturn e instanceof Map?e.clear=e.delete=e.set=()=>{\\nthrow Error(\\\"map is read-only\\\")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{\\nthrow Error(\\\"set is read-only\\\")\\n}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n]\\n;\\\"object\\\"!=typeof i||Object.isFrozen(i)||t(i)})),e}\\ne.exports=t,e.exports.default=t;var n=e.exports;class i{constructor(e){\\nvoid 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}\\nignoreMatch(){this.isMatchIgnored=!0}}function r(e){\\nreturn e.replace(/&/g,\\\"&amp;\\\").replace(/\u003C/g,\\\"&lt;\\\").replace(/>/g,\\\"&gt;\\\").replace(/\\\"/g,\\\"&quot;\\\").replace(/'/g,\\\"&#x27;\\\")\\n}function s(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t]\\n;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const o=e=>!!e.kind\\n;class a{constructor(e,t){\\nthis.buffer=\\\"\\\",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){\\nthis.buffer+=r(e)}openNode(e){if(!o(e))return;let t=e.kind\\n;t=e.sublanguage?\\\"language-\\\"+t:((e,{prefix:t})=>{if(e.includes(\\\".\\\")){\\nconst n=e.split(\\\".\\\")\\n;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${\\\"_\\\".repeat(t+1)}`))].join(\\\" \\\")\\n}return`${t}${e}`})(t,{prefix:this.classPrefix}),this.span(t)}closeNode(e){\\no(e)&&(this.buffer+=\\\"\u003C/span>\\\")}value(){return this.buffer}span(e){\\nthis.buffer+=`\u003Cspan class=\\\"${e}\\\">`}}class c{constructor(){this.rootNode={\\nchildren:[]},this.stack=[this.rootNode]}get top(){\\nreturn this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){\\nthis.top.children.push(e)}openNode(e){const t={kind:e,children:[]}\\n;this.add(t),this.stack.push(t)}closeNode(){\\nif(this.stack.length>1)return this.stack.pop()}closeAllNodes(){\\nfor(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}\\nwalk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){\\nreturn\\\"string\\\"==typeof t?e.addText(t):t.children&&(e.openNode(t),\\nt.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){\\n\\\"string\\\"!=typeof e&&e.children&&(e.children.every((e=>\\\"string\\\"==typeof e))?e.children=[e.children.join(\\\"\\\")]:e.children.forEach((e=>{\\nc._collapse(e)})))}}class l extends c{constructor(e){super(),this.options=e}\\naddKeyword(e,t){\\\"\\\"!==e&&(this.openNode(t),this.addText(e),this.closeNode())}\\naddText(e){\\\"\\\"!==e&&this.add(e)}addSublanguage(e,t){const n=e.root\\n;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){\\nreturn new a(this,this.options).value()}finalize(){return!0}}functi
{"title":"$:/plugins/tiddlywiki/markdown","name":"Markdown","description":"Markdown parser based on remarkable by Jon Schlinkert and remarkable-katex by Brad Howes","list":"readme usage remarkable-license remarkable-katex-license","version":"5.2.2","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/plugins/tiddlywiki/markdown/EditorToolbar/bold\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/bold\",\"list-after\":\"$:/core/ui/EditorToolbar/bold\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/bold\",\"caption\":\"{{$:/language/Buttons/Bold/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Bold/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((bold))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-operation\\\"\\n\\t$param=\\\"wrap-selection\\\"\\n\\tprefix=\\\"**\\\"\\n\\tsuffix=\\\"**\\\"\\n/>\\n\"},\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-1\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-1\",\"list-after\":\"$:/core/ui/EditorToolbar/heading-1\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/heading-1\",\"caption\":\"{{$:/language/Buttons/Heading1/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Heading1/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((heading-1))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-operation\\\"\\n\\t$param=\\\"prefix-lines\\\"\\n\\tcharacter=\\\"#\\\"\\n\\tcount=\\\"1\\\"\\n/>\\n\"},\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-2\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-2\",\"list-after\":\"$:/core/ui/EditorToolbar/heading-2\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/heading-2\",\"caption\":\"{{$:/language/Buttons/Heading2/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Heading2/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((heading-2))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-operation\\\"\\n\\t$param=\\\"prefix-lines\\\"\\n\\tcharacter=\\\"#\\\"\\n\\tcount=\\\"2\\\"\\n/>\\n\"},\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-3\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-3\",\"list-after\":\"$:/core/ui/EditorToolbar/heading-3\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/heading-3\",\"caption\":\"{{$:/language/Buttons/Heading3/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Heading3/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((heading-3))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-operation\\\"\\n\\t$param=\\\"prefix-lines\\\"\\n\\tcharacter=\\\"#\\\"\\n\\tcount=\\\"3\\\"\\n/>\\n\"},\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-4\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-4\",\"list-after\":\"$:/core/ui/EditorToolbar/heading-4\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/heading-4\",\"caption\":\"{{$:/language/Buttons/Heading4/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Heading4/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((heading-4))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-operation\\\"\\n\\t$param=\\\"prefix-lines\\\"\\n\\tcharacter=\\\"#\\\"\\n\\tcount=\\\"4\\\"\\n/>\\n\"},\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-5\":{\"title\":\"$:/plugins/tiddlywiki/markdown/EditorToolbar/heading-5\",\"list-after\":\"$:/core/ui/EditorToolbar/heading-5\",\"tags\":\"$:/tags/EditorToolbar\",\"icon\":\"$:/core/images/heading-5\",\"caption\":\"{{$:/language/Buttons/Heading5/Caption}} (Markdown)\",\"description\":\"{{$:/language/Buttons/Heading5/Hint}}\",\"condition\":\"[\u003CtargetTiddler>type[text/x-markdown]]\",\"shortcuts\":\"((heading-5))\",\"text\":\"\u003C$action-sendmessage\\n\\t$message=\\\"tm-edit-text-opera
{"title":"$:/SiteSubtitle","text":"Punk2Punk","created":"20200307101722466","modified":"20200307101724421"},
{"title":"$:/SiteTitle","text":"KawaiiPunk's Walkaway Wiki","created":"20200227010307445","modified":"20200307101716996"},
{"title":"$:/status/IsAnonymous","text":"yes","bag":"default","revision":"1"},
{"title":"$:/status/IsLoggedIn","text":"yes","bag":"default","revision":"2"},
{"title":"$:/status/IsReadOnly","text":"no","bag":"default","revision":"1"},
{"title":"$:/status/RequireReloadDueToPluginChange","text":"yes"},
{"title":"$:/status/UserName","text":"","bag":"default","revision":"1"},
{"title":"$:/StoryList","text":"","list":""},
{"title":"$:/temp/info-plugin","type":"application/json","plugin-type":"info","text":"{\n \"tiddlers\": {\n \"$:/info/browser\": {\n \"title\": \"$:/info/browser\",\n \"text\": \"yes\"\n },\n \"$:/info/node\": {\n \"title\": \"$:/info/node\",\n \"text\": \"no\"\n },\n \"$:/info/startup-timestamp\": {\n \"title\": \"$:/info/startup-timestamp\",\n \"text\": \"20220414234021434\"\n },\n \"$:/info/url/full\": {\n \"title\": \"$:/info/url/full\",\n \"text\": \"https://tiddlywiki.com/upgrade.html\"\n },\n \"$:/info/url/host\": {\n \"title\": \"$:/info/url/host\",\n \"text\": \"tiddlywiki.com\"\n },\n \"$:/info/url/hostname\": {\n \"title\": \"$:/info/url/hostname\",\n \"text\": \"tiddlywiki.com\"\n },\n \"$:/info/url/protocol\": {\n \"title\": \"$:/info/url/protocol\",\n \"text\": \"https:\"\n },\n \"$:/info/url/port\": {\n \"title\": \"$:/info/url/port\",\n \"text\": \"\"\n },\n \"$:/info/url/pathname\": {\n \"title\": \"$:/info/url/pathname\",\n \"text\": \"/upgrade.html\"\n },\n \"$:/info/url/search\": {\n \"title\": \"$:/info/url/search\",\n \"text\": \"\"\n },\n \"$:/info/url/origin\": {\n \"title\": \"$:/info/url/origin\",\n \"text\": \"https://tiddlywiki.com\"\n },\n \"$:/info/browser/screen/width\": {\n \"title\": \"$:/info/browser/screen/width\",\n \"text\": \"1600\"\n },\n \"$:/info/browser/screen/height\": {\n \"title\": \"$:/info/browser/screen/height\",\n \"text\": \"900\"\n },\n \"$:/info/darkmode\": {\n \"title\": \"$:/info/darkmode\",\n \"text\": \"yes\"\n },\n \"$:/info/browser/language\": {\n \"title\": \"$:/info/browser/language\",\n \"text\": \"en-GB\"\n }\n }\n}"},
{"title":"$:/theme","type":"text/vnd.tiddlywiki","text":"$:/themes/tiddlywiki/vanilla","bag":"default","created":"20200227001653465","modified":"20200308010121031","revision":"0"},
{"title":"$:/themes/tiddlywiki/snowwhite","name":"Snow White","author":"JeremyRuston","core-version":">=5.0.0","plugin-type":"theme","description":"Emphasises individual tiddlers","dependents":"$:/themes/tiddlywiki/vanilla","plugin-priority":"0","version":"5.2.2","type":"application/json","text":"{\"tiddlers\":{\"$:/themes/tiddlywiki/snowwhite/base\":{\"title\":\"$:/themes/tiddlywiki/snowwhite/base\",\"tags\":\"[[$:/tags/Stylesheet]]\",\"text\":\"\\\\define sidebarbreakpoint-minus-one()\\n\u003C$text text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]subtract[1]addsuffix[px]] ~[{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}] }}}/>\\n\\\\end\\n\\n\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\n.tc-sidebar-header {\\n\\ttext-shadow: 0 1px 0 \u003C\u003Ccolour sidebar-foreground-shadow>>;\\n}\\n\\n.tc-tiddler-info {\\n\\t\u003C\u003Cbox-shadow \\\"inset 1px 2px 3px rgba(0,0,0,0.1)\\\">>\\n}\\n\\n@media screen {\\n\\t.tc-tiddler-frame {\\n\\t\\t\u003C\u003Cbox-shadow \\\"1px 1px 5px rgba(0, 0, 0, 0.3)\\\">>\\n\\t}\\n}\\n\\n@media (max-width: \u003C\u003Csidebarbreakpoint-minus-one>>) {\\n\\t.tc-tiddler-frame {\\n\\t\\t\u003C\u003Cbox-shadow none>>\\n\\t}\\n}\\n\\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\\n\\t\u003C\u003Ctransition \\\"fill 150ms ease-in-out\\\">>\\n}\\n\\n.tc-tiddler-controls button.tc-selected,\\n.tc-page-controls button.tc-selected {\\n\\t\u003C\u003Cfilter \\\"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\\\">>\\n}\\n\\n.tc-tiddler-frame input.tc-edit-texteditor,\\n.tc-tiddler-frame select.tc-edit-texteditor {\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 8px rgba(0, 0, 0, 0.15)\\\">>\\n}\\n\\n.tc-edit-tags {\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 8px rgba(0, 0, 0, 0.15)\\\">>\\n}\\n\\n.tc-tiddler-frame .tc-edit-tags input.tc-edit-texteditor {\\n\\t\u003C\u003Cbox-shadow \\\"none\\\">>\\n\\tborder: none;\\n\\toutline: none;\\n}\\n\\ntextarea.tc-edit-texteditor {\\n\\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}};\\n}\\n\\ncanvas.tc-edit-bitmapeditor {\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 5px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-drop-down {\\n\\tborder-radius: 4px;\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 10px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-block-dropdown {\\n\\tborder-radius: 4px;\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 10px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-modal {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.3)\\\">>\\n}\\n\\n.tc-modal-footer {\\n\\tborder-radius: 0 0 6px 6px;\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 0 #fff\\\">>;\\n}\\n\\n\\n.tc-alert {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.6)\\\">>\\n}\\n\\n.tc-notification {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.3)\\\">>\\n\\ttext-shadow: 0 1px 0 rgba(255,255,255, 0.8);\\n}\\n\\n.tc-sidebar-lists .tc-tab-set .tc-tab-divider {\\n\\tborder-top: none;\\n\\theight: 1px;\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.0) 100%\\\">>\\n}\\n\\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.1) 100%\\\">>\\n}\\n\\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.05) 0%, rgba(255,255,255,0.05) 100%\\\">>\\n}\\n\\n.tc-message-box img {\\n\\t\u003C\u003Cbox-shadow \\\"1px 1px 3px rgba(0,0,0,0.5)\\\">>\\n}\\n\\n.tc-plugin-info {\\n\\t\u003C\u003Cbox-shadow \\\"1px 1px 3px rgba(0,0,0,0.5)\\\">>\\n}\\n\"}}}"},
{"title":"$:/themes/tiddlywiki/vanilla","name":"Vanilla","author":"JeremyRuston","core-version":">=5.0.0","plugin-type":"theme","description":"Basic theme","plugin-priority":"0","version":"5.2.2","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/themes/tiddlywiki/vanilla/themetweaks\":{\"title\":\"$:/themes/tiddlywiki/vanilla/themetweaks\",\"tags\":\"$:/tags/ControlPanel/Appearance\",\"caption\":\"{{$:/language/ThemeTweaks/ThemeTweaks}}\",\"text\":\"\\\\define lingo-base() $:/language/ThemeTweaks/\\n\\n\\\\define replacement-text()\\n[img[$(imageTitle)$]]\\n\\\\end\\n\\n\\\\define backgroundimage-dropdown()\\n\u003Cdiv class=\\\"tc-drop-down-wrapper\\\">\\n\u003C$set name=\\\"state\\\" value=\u003C\u003Cqualify \\\"$:/state/popup/themetweaks/backgroundimage\\\">>>\\n\u003C$button popup=\u003C\u003Cstate>> class=\\\"tc-btn-invisible tc-btn-dropdown\\\">{{$:/core/images/down-arrow}}\u003C/$button>\\n\u003C$reveal state=\u003C\u003Cstate>> type=\\\"popup\\\" position=\\\"belowleft\\\" text=\\\"\\\" default=\\\"\\\" class=\\\"tc-popup-keep\\\">\\n\u003Cdiv class=\\\"tc-drop-down\\\" style=\\\"text-align:center;\\\">\\n\u003C$macrocall $name=\\\"image-picker\\\" actions=\\\"\\\"\\\"\\n\\n\u003C$action-setfield\\n\\t$tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\\\"\\n\\t$value=\u003C\u003CimageTitle>>\\n/>\\n\\n\u003C$action-deletetiddler $tiddler=\u003C\u003Cstate>>/>\\n\\n\\\"\\\"\\\"/>\\n\u003C/div>\\n\u003C/$reveal>\\n\u003C/$set>\\n\u003C/div>\\n\\\\end\\n\\n\\\\define backgroundimageattachment-dropdown()\\n\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\\\" default=\\\"scroll\\\">\\n\u003Coption value=\\\"scroll\\\">\u003C\u003Clingo Settings/BackgroundImageAttachment/Scroll>>\u003C/option>\\n\u003Coption value=\\\"fixed\\\">\u003C\u003Clingo Settings/BackgroundImageAttachment/Fixed>>\u003C/option>\\n\u003C/$select>\\n\\\\end\\n\\n\\\\define backgroundimagesize-dropdown()\\n\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\\\" default=\\\"scroll\\\">\\n\u003Coption value=\\\"auto\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Auto>>\u003C/option>\\n\u003Coption value=\\\"cover\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Cover>>\u003C/option>\\n\u003Coption value=\\\"contain\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Contain>>\u003C/option>\\n\u003C/$select>\\n\\\\end\\n\\n\u003C\u003Clingo ThemeTweaks/Hint>>\\n\\n! \u003C\u003Clingo Options>>\\n\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\\\">\u003C\u003Clingo Options/SidebarLayout>>\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\\\">\u003Coption value=\\\"fixed-fluid\\\">\u003C\u003Clingo Options/SidebarLayout/Fixed-Fluid>>\u003C/option>\u003Coption value=\\\"fluid-fixed\\\">\u003C\u003Clingo Options/SidebarLayout/Fluid-Fixed>>\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/stickytitles\\\">\u003C\u003Clingo Options/StickyTitles>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Options/StickyTitles/Hint>>// |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/stickytitles\\\">\u003Coption value=\\\"no\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"yes\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003C\u003Clingo Options/CodeWrapping>>\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003Coption value=\\\"pre\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"pre-wrap\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n\\n! \u003C\u003Clingo Settings>>\\n\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\\\">\u003C\u003Clingo Settings/FontFamily>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\\\" default=\\\"\\\" tag=\\\"input\\\"/> | |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/settings/co
{"title":"$:/themes/tiddlywiki/vanilla/options/sidebarlayout","text":"fluid-fixed","created":"20200308010142424","modified":"20200308010142424"},
{"title":"$:/view","type":"text/vnd.tiddlywiki","text":"classic","bag":"default","created":"20200227001719873","modified":"20200308010219574","revision":"0"},
{"title":"A cheatsheet on discourse","type":"text/html","text":"\u003Cq>You should attempt to re-express your target's position so clearly, vividly, and fairly that your target says, “Thanks, I wish I'd thought of putting it that way.”\u003C/q>\u003Ch5>— Rapoport's First Rule\u003C/h5>\u003Cp>The arguments rankings are taken from \u003Ca href='http://slatestarcodex.com/2018/05/08/varieties-of-argumentative-experience/' class='external' target='_blank'>Scott Alexander\u003C/a>, and the responses rankings are taken from \u003Ca href='http://www.paulgraham.com/disagree.html' class='external' target='_blank'>Paul Graham\u003C/a>.\u003C/p>\u003Ch3>Argument Ranking\u003C/h3>\n\u003Ctable border='1'>\n \u003Ctr>\u003Ctd>●●●●●\u003C/td>\u003Ctd>High-level generators\u003C/td>\u003Ctd>Disagreements that remain when everyone understands exactly what's being argued, and agrees on what all the evidence says, but have vague and hard-to-define reasons for disagreeing.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●●○\u003C/td>\u003Ctd>Operationalizing\u003C/td>\u003Ctd>Where both parties understand they're in a cooperative effort to fix exactly what they're arguing about.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●○○\u003C/td>\u003Ctd>Survey of evidence\u003C/td>\u003Ctd>Not trying to devastate the other person with a mountain of facts and start looking at the studies and arguments on both sides and figuring out what kind of complex picture they paint.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●○○\u003C/td>\u003Ctd>Disputing definitions\u003C/td>\u003Ctd>Argument hinges on the meaning of words, or whether something counts as a member of a category or not.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●○○○\u003C/td>\u003Ctd>Single Studies\u003C/td>\u003Ctd>Better than scattered facts, proving they at least looked into the issue formally.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●○○○\u003C/td>\u003Ctd>Demands for rigor\u003C/td>\u003Ctd>Attempts to demand that an opposing argument be held to such strict standards that nothing could possibly clear the bar.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●○○○○\u003C/td>\u003Ctd>Single Facts\u003C/td>\u003Ctd>One fact, which admittedly does support their argument, but presented as if it solves the debate in and of itself.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●○○○○\u003C/td>\u003Ctd>Gotchas\u003C/td>\u003Ctd>Short claims that purport to be devastating proof that one side can't possibly be right.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>○○○○○\u003C/td>\u003Ctd>Social shaming\u003C/td>\u003Ctd>A demand for listeners to place someone outside the boundary of whom deserve to be heard.\u003C/td>\u003C/tr>\n\u003C/table>\n\n\u003Ch3>Response Ranking\u003C/h3>\n\n\u003Ctable border='1'>\n \u003Ctr>\u003Ctd>●●●●●●\u003C/td>\u003Ctd>Central point\u003C/td>\u003Ctd>Commit to refute explicitly the central point.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●●●○\u003C/td>\u003Ctd>Refutation\u003C/td>\u003Ctd>Argue a conflicting passage, explain why it's mistaken.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●●○○\u003C/td>\u003Ctd>Counterargument\u003C/td>\u003Ctd>Contradict with added reasoning or evidence.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●●○○○\u003C/td>\u003Ctd>Contradiction\u003C/td>\u003Ctd>State the opposing case, what.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●●○○○○\u003C/td>\u003Ctd>Responding to Tone\u003C/td>\u003Ctd>Responding to the author's tone, how.\u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>●○○○○○\u003C/td>\u003Ctd>Ad Hominem\u003C/td>\u003Ctd>Attacking the author directly, who.\u003C/td>\u003C/tr>\n\u003C/table>\n\n\u003Ch3>Emotional Reaction\u003C/h3>\n\n\u003Ctable border='1'>\n \u003Ctr>\u003Ctd>Seduction\u003C/td>\u003Ctd>You are led to feel that the fulfillment of your dreams depends on your doing what the other is encouraging you to do. \u003C/td>\u003C/tr>\n \u003Ctr>\u003Ctd>Alignment\u003C/td>\u003Ctd>The interes
{"title":"A comparison of cryptographic keycards","type":"text/x-markdown","text":"https://lwn.net/Articles/736231/\n\nGreat article from 2017 about different PGP smartcards.","created":"20210109171727684","modified":"20210227182241969","tags":"Security Tech"},
{"title":"A Libertarian Walks Into a Bear: Author Matthew Hongoltz-Hetling on the Free State Project","type":"text/x-markdown","text":"https://www.vox.com/policy-and-politics/21534416/free-state-project-new-hampshire-libertarians-matthew-hongoltz-hetling\n\nIt refers to right wing Libertarians in the United States and one of their failed projects.","created":"20201223004536201","modified":"20201223004624763","tags":"Organising"},
{"title":"Abdullah Öcalan On Methodology and the Regime of the Truth","type":"text/x-markdown","text":"https://jikurd.noblogs.org/post/2017/01/01/textes-7-abdullah-ocalan-on-methodology-and-the-regime-of-the-truth/\n\n> An Introduction to the Problematic of Methodology and Truth\n\nThis is all very interesting.","created":"20201211135625845","modified":"20201211135718866","tags":"Psychology Organising"},
{"title":"About RSS feed","type":"text/x-markdown","text":"This site is really useful for explaining to people about how awesome RSS feeds are:\n\nhttps://aboutfeeds.com/","created":"20200902121355071","modified":"20200902121426994","tags":"Tech"},
{"title":"Acessing Android storage using Termux","type":"text/x-markdown","text":"https://wiki.termux.com/wiki/Internal_and_external_storage\n\n There are three main types of storage in Termux:\n\n App-private storage: Files put in $HOME, available from inside Termux (or when explictly picked, when e.g. attaching a file to a mail).\n\n Shared internal storage: Storage in the device available to all apps. On Android 6.0 this requires the user to explicitly grant access to for Termux to access it.\n\n External storage: Storage on external SD cards. Each app has a private folder on the external SD card, and interchange between them needs to use a special API not yet available in Termux. SAF-based access is not possible as shell is executed outside of Android framework.","created":"20201223002723132","modified":"20201223002838854","tags":"Tech"},
{"title":"Adam Curtis","type":"text/x-markdown","text":"## In Defence of Adam Curtis \nhttps://tribunemag.co.uk/2021/02/in-defence-of-adam-curtis\n\n> For anyone with more than a few socialists (or at least fellow travellers) on their social media feeds, it began as a trickle, and then a gush. The oven-ready critiques came thick and fast. It could only mean one thing: Adam Curtis has something new out.\n>\n> Over the course of the 2010s, his films grew from minor BBC oddities to veritable collective viewing experiences. Not far behind came the backlash: first as parodies of varying quality, then concerns about what his hypnotic style might be doing to impressionable minds, followed by a chorus of ostentatious boredom. The subject of the 2021 edition of all this fuss merits some closer examination.\n\n## Bugger\nhttps://www.bbc.co.uk/blogs/adamcurtis/entries/3662a707-0af9-3149-963f-47bea720b460\n\n## Social media is a scam\nhttps://www.idler.co.uk/article/adam-curtis-social-media-is-a-scam/\n","created":"20210309145010280","modified":"20210309145354861","tags":"Writing"},
{"title":"ADHD and Sleep","type":"text/x-markdown","text":"## Studies\n- Sleep problems in children with attention-deficit/hyperactivity disorder: prevalence and the effect on the child and family. - https://www.ncbi.nlm.nih.gov/pubmed/18391142\n- Sleep problems in children with attention-deficit/hyperactivity disorder: prevalence and the effect on the child and family. - https://pdfs.semanticscholar.org/a1c2/58e44701371bd465e4946ca51264b13675a5.pdf\n- 30th ECNP Congress webcast: Circadian rhythm and sleep in ADHD cause or life style factor? - https://www.youtube.com/watch?v=SkuIL-Ljmwo\n- ADHD and Sleep Disorders: Are Kids Getting Misdiagnosed? - https://childmind.org/article/adhd-sleep-disorders-misdiagnosed/\n- ADHD: A 24-Hour Disorder - https://www.psychiatrictimes.com/special-reports/adhd-24-hour-disorder\n- Delayed circadian rhythm in adults with attention-deficit/hyperactivity disorder and chronic sleep-onset insomnia.- https://www.ncbi.nlm.nih.gov/pubmed/20163790\n- https://en.wikipedia.org/wiki/Melatonin\n\n## Videos\n- 31 Days of Loving Your Brain - Talking to Tallulah about ADHD - https://www.youtube.com/watch?v=s2XWuF0TN1A\n- Getting My ADHD Diagnosis As An Adult - https://www.youtube.com/watch?v=ONuKw5QoJHk","created":"20200421095814975","modified":"20200421102907184","tags":"Care"},
{"title":"ADHD folks on Twitter","type":"text/x-markdown","text":"- https://nitter.cc/adhd_alien\n- ADHD and disorded eating: https://nitter.cc/samdylanfinch/status/1366609304589987840","created":"20210309152134158","modified":"20210309152246065","tags":"Care"},
{"title":"Air Quality Monitoring","type":"text/x-markdown","text":"My friend sent me a bunch of links from their research into Air Quality Monitoring.\n\n- http://www.openair-project.org/\n-chttps://davidcarslaw.github.io/openair/\n- https://shop.pimoroni.com/products/enviro?variant=31155658457171\n- https://create.arduino.cc/projecthub/alfred333/co2-monitoring-with-k30-sensor-86f6d9\n- http://www.livpi.com/store/c16/Arduino.html\n- https://forum.mysensors.org/topic/6528/mh-z19-co2-sensor/20\n- https://plumelabs.com/en/flow/\n- https://mobile.twitter.com/luftdaten\n- https://luftdaten.info/feinstaubsensor-bauen/\nhttp://www.livpi.com/store/p53/Arduino_kit_2%3A_K30_CO2_sensor%2C_LCD1602_I2C_display%2C_connection_cables_.html\n- https://learn.pimoroni.com/tutorial/sandyj/enviro-plus-and-luftdaten-air-quality-station\n- https://smartcitizen.me (This one doesn't use NDIR for the Co2 monitor but is cool)\n\nThe SmartCitizen kit looks the most interesting to me as I am particularly time poor at the moment.","created":"20200307222555620","modified":"20200307222934113","tags":"Ecology"},
{"title":"Airwindows audio plug-ins","type":"text/x-markdown","text":"https://www.airwindows.com/\n\nAirwindows are a great maker of audio plug-ins. There's VST plug-ins for Linux as well as Mac and Windows. They don't have any GUI so rely on your host DAW to take care of that. They're also open source.\n\nIn short they're excellent. But there's so many of them! There's 218 at time of writing. Here is a handy guide someone made:\nhttps://airwindowscheatsheet.aboni.dev/\n\nThe developer also makes a videos about each new plug-in. Here is one of my favourite called cstrip.\nhttps://www.airwindows.com/?s=cstrip\n\nThis is a cool thread of people using Airwindows:\nhttps://linuxmusicians.com/viewtopic.php?f=40&t=23169","created":"20210614170319631","modified":"20210615122148875","tags":"[[Music Production]]"},
{"title":"Alpkit Gear I have my eye on","type":"text/x-markdown","text":"- https://alpkit.com/products/hunka\n- https://alpkit.com/products/mora-hammock\n- https://alpkit.com/products/elan\n- https://alpkit.com/products/rana-waterproof-socks","created":"20210109172728201","modified":"20210109172855459","tags":"Travel Cycling"},
{"title":"Android Encryption","type":"text/x-markdown","text":"- https://source.android.com/security/encryption\n- https://blog.cryptographyengineering.com/2016/11/24/android-n-encryption/\n- https://source.android.com/security/encryption/full-disk\n- https://source.android.com/security/encryption/file-based","created":"20210131215544446","modified":"20210131215815433","tags":"Security Tech"},
{"title":"Ant Media Server","type":"text/x-markdown","text":"This looks like a good project. Could hook up to OBS and do some live streaming. Would be interested in how it performs.\n\n- https://antmedia.io/\n- https://github.com/ant-media/Ant-Media-Server\n- https://github.com/ant-media/Ant-Media-Server/wiki/Open-Broadcaster-Software-Publishing\n- https://github.com/ant-media/Ant-Media-Server/wiki","created":"20200902121206083","modified":"20200902121326030","tags":"Social Tech"},
{"title":"Anxiety - Browser based game","type":"text/x-markdown","text":"Haven't sat down to play this yet but it was recommended by a friend.\n\nhttps://ncase.me/anxiety/","created":"20200716124314585","modified":"20200716124402406","tags":"Tech Gaming"},
{"title":"Archiving websites onto dat","type":"text/x-markdown","text":"One really awesome way to archive sites to dat is using [httrack](https://www.httrack.com/) which is a free software website archiver.\n\nIt's super easy to use and there's loads of options for the most complex needs.\n\nOn it's simplest level, you just run `httrack URL` and then it will pull everything down to a local directory. You can run it again to update your local copy. Then simply use [Beaker Browser](dat://beakerbrowser.com/) to make that archive into a new site. You also get the version tracking of Beaker.\n","created":"20200307170446165","modified":"20200307230128512","tags":"P2P Tech"},
{"title":"Autonomous Design Group","type":"text/x-markdown","text":"https://www.weareadg.org/\n\n> Autonomous Design Group is an independent collective of designers, artists and creatives opposed to capitalism and authoritarianism.\n\n","created":"20201223011114678","modified":"20201223011202508","tags":"Organising Art"},
{"title":"Belarus: Anarchists in the Uprising against the Dictatorship","type":"text/x-markdown","text":"I'd like to express solidarity with struggles against authoritarianism around the world. Right now that means learning more and raising awareness about the situation in Belarus.\n\n- https://crimethinc.com/2020/08/12/belarus-anarchists-in-the-uprising-against-the-dictatorship-an-interview\n- https://abc-belarus.org/\n- https://pramen.io/en/main/\n- https://soundcloud.com/popularfrontcast/89-the-anti-dictatorship-uprising-in-belarus","created":"20200817123950422","modified":"20200817124424169","tags":"Organising"},
{"title":"Beyond-the-frontlines-The-building-of-the-democratic-system-in-North-and-East-Syria-Report-Rojava-Information-Center-December-2019-V4.pdf","type":"application/pdf","text":"JVBERi0xLjQNJeLjz9MNCjI0ODggMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgMzUzODYxMS9PIDI0OTAvRSAyOTM1NzYvTiA2Mi9UIDM0ODg3MjkvSCBbIDgzNyAxNTg5XT4+DWVuZG9iag0gICAgICAgDQp4cmVmDQoyNDg4IDI2DQowMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDI2NTEgMDAwMDAgbg0KMDAwMDAwMjgxNCAwMDAwMCBuDQowMDAwMDAzODcxIDAwMDAwIG4NCjAwMDAwMDQ2NTMgMDAwMDAgbg0KMDAwMDAwNDc2OCAwMDAwMCBuDQowMDAwMDA1MDI1IDAwMDAwIG4NCjAwMDAwMDU2NzUgMDAwMDAgbg0KMDAwMDAwNjYyOSAwMDAwMCBuDQowMDAwMDA3ODYwIDAwMDAwIG4NCjAwMDAwMDkxNDggMDAwMDAgbg0KMDAwMDAxMDMwOSAwMDAwMCBuDQowMDAwMDExMzk4IDAwMDAwIG4NCjAwMDAwMTI1NjkgMDAwMDAgbg0KMDAwMDAxMzY3NyAwMDAwMCBuDQowMDAwMDE0NzkxIDAwMDAwIG4NCjAwMDAwMjcyMDIgMDAwMDAgbg0KMDAwMDAyNzMyNyAwMDAwMCBuDQowMDAwMDI5NzcxIDAwMDAwIG4NCjAwMDAwMjk4MTIgMDAwMDAgbg0KMDAwMDAyOTg5MCAwMDAwMCBuDQowMDAwMDMwMTcyIDAwMDAwIG4NCjAwMDAwMzIyNjkgMDAwMDAgbg0KMDAwMDI5MzUxNCAwMDAwMCBuDQowMDAwMDAyNDI2IDAwMDAwIG4NCjAwMDAwMDA4MzcgMDAwMDAgbg0KdHJhaWxlcg0KPDwvU2l6ZSAyNTE0L1Jvb3QgMjQ4OSAwIFIvSW5mbyAzNzggMCBSL0lEWzxFMDEwRTIzMTQxMzEwNDRCQTE1QTg4ODVCNEVERTRGMT48RDQ5MkU1RUI1RTBEQzg0Mzg0NkE3NTUxMzFDNjBGNDc+XS9QcmV2IDM0ODg3MTYvWFJlZlN0bSAyNDI2Pj4NCnN0YXJ0eHJlZg0KMA0KJSVFT0YNCiAgICAgICAgICAgIA0KMjUxMyAwIG9iag08PC9DIDI3OTcvRmlsdGVyL0ZsYXRlRGVjb2RlL0kgMjg1Mi9MZW5ndGggMTQ5NS9TIDI0NTQ+PnN0cmVhbQ0KaN7MVutvFFUUP3dm9lU6stuW3enObrvd0vdr291SFhAXXB5dy6t0oNIWi8oWKNQWkC7IYwA1G3yk8AEREoLGR2MINvqF+MoGiAE1PqIxGkwgEV9RIyofUJvomTuPnQX+ACeZ2Xt/5/zO+d1zz9xZAGAAuEtgBbB+CYWQvQoRswMH9uV06hu24PMlmIpPO95sxg4EIAawXzE753EqLfBMiSxFuEsHdl2Nn7P8EjtfLf4d/qDj4Fd5sbbCU3PHbfbMmfG83/s+z3TPsT4b+7i/lbP+FvtI8LYlTp8amsx3EaezyMfVfJh05jHk7f5mHzlL3pT5I2w5XB5zLCa9cuvzW0fJfCgqIldiS8ati+HbmL93ygaycKIqwlgzHU77GPFkCp9mtsmH+wEcTrnouyPtrx6VLhzd+MPxvpdf2TR+sm/guaVvnVj/xlPt5Z3tFZ9UXzs0yy11vXioL3K5Y4wuhGE5UuwR/b4Sgfe6lZno9/hKiqvKS6cjUBYMVFYoaHlpFRqq6Zz3MjhVXafriDpFPFRfp7s11dY0NmQtLeHm+rqQyqAm3htRrOHmFtVB40W8DDLCzW0zWG5ma1QLFmGQLPpnsdzd4eY5swUagdq8PLWpeaJaZNVbiWr2VFB1KegdNYfIWlAOGs2sCLUaMnOpEZVrmIRbo1Jd98bumT9vrlmcIUO4swyzOqYuVC/6l7TftyiOhGW+kkSxiYX7tGBxx9KFGtdcB9N+efyIsy3N4a5VxSWrfegr8A2NEW9NrbupMhCUKpavXFHWyXj8IuFYX3HJ/Wu6u1avqg/VRaVONHkbGmvctU09fHbH0IxO2CwC9cB969E7KIHh0aCv1601jMoTjG02o8iImlojQltKjY+JEloOzJDAKZqU8CrmZrDn1LylVeWJbqpLkVVbw2MFvBizR+pc6V7euKJJqRHpi3NhX3OJv//Bhx5Yx67tFRWdDbSGZYFKd6SR91YEmYTRuEqtzF3LJIwyP6xqptwcw20cbVtwpOyhMMCv35BkDN9orptWV16pqOIe3cwPDW7ZtFHrNKNrjN4zetLL3yGEkSaRsykqHBdGeO8jw1tNCo3KC7yZfYtIwewZVTw5Mir60dHDavQdeq6hwZ5Ht21nRtW+QGt0JzW5e4YGU4/tYkbVHUWDsIdXwN379tKVa9H3Y3j54BOPH8jNndWrYdkNUFj662GCBf2VyG5v1ICMl0/Rbnr/3EqVE1pQtcxuBseIuL0AMrDhcFtaVg5ULp5Kp3HIxeOL6AAvmzZwuZOKUZu4XMmBtDEF4qJEjNQqURxdCoLhGSojTU/rlDpggqkshomzk2Bl0uwfnB7PTq1JPZ/27dNloSUri6LK0CJJUhIvLYBmVTVoEyYYj8el1Wmzh6swHF+ok7SK4JXSpwsklZCVoA2tOcrVdcvmVdP6JY1FqGZLUr1yQKxlzlKZrGYmaLLY8GFLUZyiyiAcDlNkVHWxSCm9ekbxlYrTdanFUVhtKSMgFWxmmkFFmstjrg5NpAu1pXJhnW0zxdEbzFwZl8eAaNep3eMKVikwVif9f/y7gmKvQenIdvx14/0klS9CASFyU4j0w/dwIhO9XvAp9ysR5fn9rqtclEw9bwWSdowAK7MhdtLu/leQmdCZSdZhvSE3yO93wc8wG6rHHBPMobzXgZkgKdy6P+TyMfYabLXeODcQIxcZCRNVXmcvQh2IMTFgC8FPjncyNrAdY6fAe+TdTH49DMNOuUmGbtR2LkOGoZe5CdMyzITlNPoUZmwB0sXctP2VsV7l7LDFLslijHTDP0qDTJALTBm8BlOd9kDwCqYgcn49uQ5ipkHG7DdxwAYqvyGjJ8+C1DicgjxYi4hlJrQcFsHjDASPf0EkmQ1gFddBvlwcmLbms93a4McXcOCRLZV3TToKAE7B7RfpgsixZWpZDzvwtwzs+9XDc8/ufYN7h3biibsDj+MRPPU341dlAD9FSNsFrbO+Vvh4//mfAAMA63JnLA0KZW5kc3RyZWFtDWVuZG9iag0yNTEyIDAgb2JqDTw8L0RlY29kZVBhcm1zPDwvQ29sdW1ucyA0L1ByZWRpY3RvciAxMj4+L0ZpbHRlci9GbGF0ZURlY29kZS9JbmRleFszNzkgMjEwOV0vTGVuZ3RoIDcwL1NpemUgMjQ4OC9UeXBlL1hSZWYvV1sxIDIgMV0+PnN0cmVhbQ0KaN7s0TEBADAMw7CkGEtvXAekegTAnulmkhSH6NPAc3gOz+E5PIfn8Byew3N4Ds/hOTyH5/AcnnsOz+E5Lj3/AgwA6KIl7w0KZW5kc3RyZWFtDWVuZG9iag0yNDg5IDAgb2JqDTw8L0xhbmcoZW4tR0IpL01hcmtJbmZvPDwvTWFya2VkIHRydWU+Pi9NZXRhZGF0YSAzNzcgMCBSL1BhZ2VzIDM2MiAwIFIvU3RydWN0VHJlZVJvb3QgMzc5IDAgUi9UeXBlL0NhdGFsb2cvVmlld2VyUHJlZmVyZW5jZXM8PC9EaXJlY3Rpb24vTDJSPj4+Pg1lbmRvYmoNMjQ5MCAwIG9iag08PC9BcnRCb3hbMC4wIDAuMCA1OTUuMjc2IDg0MS44OV0vQmxlZWRCb3hbMC4wIDAuMCA1OTUuMjc2IDg0MS44OV0vQ29udGVudHNbMjQ5NSAwIFIgMjQ5NiAwIFIgMjQ5NyAwIFIgMjQ5OCAwI
{"title":"Bikeshedding","type":"text/x-markdown","text":"> The term was coined as a metaphor to illuminate Parkinsons Law of Triviality. Parkinson observed that a committee whose job is to approve plans for a nuclear power plant may spend the majority of its time on relatively unimportant but easy-to-grasp issues, such as what materials to use for the staff bikeshed, while neglecting the design of the power plant itself, which is far more important but also far more difficult to criticize constructively. It was popularized in the Berkeley Software Distribution community by Poul-Henning Kamp[1] and has spread from there to the software industry at large. \n\n*Source: https://en.wiktionary.org/wiki/bikeshedding*","created":"20200817123530690","modified":"20200817123620518","tags":"Social Organising"},
{"title":"Birds aren't real meme from Chaos Congress","type":"text/x-markdown","text":"Someone documented the very amusing physical meme from 35c3.\n\nhttps://commons.wikimedia.org/wiki/Category:Birds_arent_real_meme","created":"20201211140115659","modified":"20201211140208737","tags":"Tech"},
{"title":"Black Panther Party Programs of Survival","type":"text/x-markdown","text":"http://www.itsabouttimebpp.com/Survival_Programs/survival_programs.html\n\n The Black Panther Party instituted or envisioned starting all of these programs as part of a process to help African Americans and other oppressed peoples meet their basic necessities so that they might organize to acquire the resources for self-determination and empowerment.\n\nSome of these programs still exist or were models for many of today's human and community service programs.\n\n GEORGE JACKSON MEDICAL CLINIC\n Provides free medical treatment and preventative medical care for the people. \n\n THE SICKLE CELL ANEMIA RESEARCH FOUNDATION\n Established to test and create a cure for Sickle Cell Anemia The foundation informs people about Sickle Cell Anemia and maintains an advisory committee of doctors researching this crippling disease. \n\n PEOPLE'S FREE DENTAL PROGRAM\n (Being implemented) Provides free dental check-ups, treatment and an educational program for dental hygiene. \n\n PEOPLE'S FREE OPTOMETRY PROGRAM\n (Being implemented) Provides free eye examinations, treatment and eyeglasses for the people. \n\n PEOPLE'S FREE AMBULANCE PROGRAM\n Provides free, rapid transportation for sick or injured people without time-consuming checks into the patients' financial status or means. \n\n FREE FOOD PROGRAM\n Provides free food to Black and other oppressed people. \n\n FREE BREAKFAST PROGRAM\n Provides children with a free nourishing, hot breakfast every school morning \n\n FOOD COOPERATIVE PROGRAM\n Provides food for people through community participation and community cooperative buying. \n\n INTERCOMMUNAL NEWS SERVICE\n Provides news and information about the world and Black and oppressed communities. \n\n PEOPLE'S FREE COMMUNITY EMPLOYMENT PROGRAM\n Provides free job-finding services to poor and oppressed People. \n\n SHOE PROGRAM\n (Being Implemented) Provides free shoes, made at the Peoples Free Shoe Factory, to the people. \n\n PEOPLES FREE CLOTHING PROGRAM\n Provides new, stylish and quality clothing free to people. \n\n PEOPLE'S FREE LEGAL AID AND EDUCATIONAL PROGRAM\n Provides legal aid classes and full legal assistance to people who are in need. \n\n FREE BUSING TO PRISONS PROGRAM\n Provides free transportation to prisons for families and friends of prisoners. \n\n FREE COMMISSARY FOR PRISONERS PROGRAM\n Provides imprisoned men and women with funds to purchase necessary commissary items. \n\n SENIORS AGAINST A FEARFUL Environment (S.A.F.E.) Program\n Provides free transportation and escort service for senior citizens to and from community banks on the first of each month. \n\n PEOPLE'S COOPERATIVE HOUSING PROGRAM\n Provides, with federal government aid, decent, low-cost and high-quality housing for Black and poor communities. \n\n PEOPLE'S FREE PLUMBING AND MAINTENANCE PROGRAM\n Peoples Free Plumbing and Maintenance Program Provides free plumbing and repair services to improve peoples homes. \n\n FREE PEST CONTROL\n Free household extermination of rats, roaches and other disease carrying pests and rodents. \n\n PEOPLES COOPERATIVE HOUSING PROGRAM\n Provides, with federal government aid, decent, low cost and high quality housing for Black and poor communities. \n\n OAKLAND COMMUNITY SCHOOL\n Provides Black and other oppressed children with a scientific method of thinking about and analyzing things. This method develops basic skills for living in this society. \n\n LIBERATION SCHOOLS: FREE MUSIC AND DANCE PROGRAMS\n Provides children free supplementary educational facilities and materials to promote a correct view of their role in the society and provides support for the Music and Dance programs of the Oakland Community School. \n\n CHILD DEVELOPMENT CENTER\n Provides 24-hour childcare facilities for infants and children between the ages of 2 months and three years Youth are engaged in a scientific pr
{"title":"Books","type":"text/x-markdown","text":"## Wireless Networking in the Developing World\nIf it is legal to do so, I will be distributing these books using [hypercore](https://beakerbrowser.com/) here:\n[hyper://d4da06fac80e368ab614fb208d23fe8ddb441285f4a9cf06437f8e641a30c4a0/](hyper://d4da06fac80e368ab614fb208d23fe8ddb441285f4a9cf06437f8e641a30c4a0/)\n\nPlease seed!\n\n### Links\n- http://www.wndw.net/book.html\n- https://www.bookdepository.com/Wireless-Networking-Developing-World-Wireless-Networking-Authors/9781484039359\n\n## Debian Administrators Handbook\n- https://www.bookdepository.com/Debian-Administrators-Handbook-Debian-Jessie-from-Discovery-Mastery-Raphael-Hertzog/9791091414043\n","created":"20200513133602483","modified":"20200627154824066","tags":""},
{"title":"Books To Read","type":"text/x-markdown","text":"## The History, Culture and Politics of Queer Life in Wales\nEdited by Huw Osborne,\nDistributed for University of Wales Press \n\nThe relationship between the idea of the nation and queer sexuality has long been a fraught one, for the sustaining myths of the former are often at odds with the needs of the latter. Queer Wales is a collection of multidisciplinary essays that introduces readers to important historical and cultural figures and moments in queer life in Wales from the eighteenth century to the present. The book considers literature, art history, film, television, drama, crime, motherhood, and education, among other topics, and addresses some of the urgent questions of queer belonging that face Wales today.\n\nAcknowledgements\nList of Illustrations and Figures\nNotes on Contributors\nIntroduction\n Huw Osborne\n \nI. The Queer Past before 1900\n \n1. Queer Loss: Felicia Hemans, (Trans)nationalisms and the Welsh Bard\n Daniel Hannah\n \n2. Gender difference is nothing: Cranogwen and Victorian Wales\n Jane Aaron\n \n3. Please dont whip me this time: The Passions of George Powell of Nant-Eos\n Harry Heuser\n \n4. From Huw Arwystli to Siôn Eirian: Representative Examples of Cadi/Queer Life from Medieval to Twentieth-century Welsh Literature\n Mihangel Morgan\n \nII. Placing Queer Wales after 1900\n \n5. A queer kind of fancy: Women, Same-sex Desire and Nation in Welsh Literature\n Kirsti Bohata\n \n6. Not friends / But fellows in a union that ends: Associations of Welshness and Non-heteronormativity in Edward Thomas\n Andrew Webb\n \n7. Fairy-tale Drag and the Transgender Nation in Rhys Davies, Erica Wooff and Jan Morris\n Huw Osborne\n \nIII. Building Queer Wales Post-Devolution\n \n8. Lesbian Motherhood in the South Wales Valleys: A Narrative Exploration\n Alys Einion\n \n9. Living in Fear: Homophobic Hate Crime in Wales\n Matthew Williams and Jasmin Tregidga\n \n10. Heb Addysg, Heb Ddawn (Without Education, Without Gift): LGBTQ Youth in Educational Settings in Wales\n John Sam Jones\n \nIV. Performing Contemporary Queer Wales\n \n11. Omnisexuality and the City: Exploring National and Sexual Identity through BBC Wales Torchwood\n Rebecca Williams and Ruth McElroy\n \n12. Queer/Welsh and Welsh/Queer: Performing Hybrid Wales\n Stephen Greer","created":"20200416114047030","modified":"20200420200407117","tags":"Lists"},
{"title":"Boosting off-grid resilience","type":"text/x-markdown","text":"Here is a sort of TO BUY list of things I would like to boost my capacity in a situation of off-grid/survival/scarcity. \n\nNot necessarily the exact product I'm going to choose. Just popping it here in case anyone is interested.\n\n## Communications\n### 2x BAOFENG UV-5R III UHF/VHF Walkie Talkies Tri-Band FM Two Way Radio Long Range\n[https://www.ebay.co.uk/itm/264339570649](https://www.ebay.co.uk/itm/264339570649)\n\n## Tools\n### A nice knife\n\n### A multi-tool\n\n### 9 in 1 Outdoor Kit Emergency Equipment Box\n[https://www.ebay.co.uk/itm/9-in-1-SOS-Outdoor-Kit-Emergency-Equipment-Box-Camping-Survival-Gear-Kit-UK/153170474108](https://www.ebay.co.uk/itm/9-in-1-SOS-Outdoor-Kit-Emergency-Equipment-Box-Camping-Survival-Gear-Kit-UK/153170474108)\n\n## Power\n### 20W Solar Panel kit 12V battery Charge w/ Controller \n[https://www.ebay.co.uk/itm/20W-Solar-Panel-kit-12V-battery-Charge-w-Controller-Caravan-Boat-Home-Camp-RV/303173162123](https://www.ebay.co.uk/itm/20W-Solar-Panel-kit-12V-battery-Charge-w-Controller-Caravan-Boat-Home-Camp-RV/303173162123)\n\n### 100W Solar Panel\nhttps://www.alibaba.com/product-detail/High-Efficiency-Sunpower-Foldable-Flexible-100w_62313835644.html\n\n### Travel Solar USB Charger 6W and battery\n[https://www.bimblesolar.com/solar/small-panels/usb-solar-6w-sunpower](https://www.bimblesolar.com/solar/small-panels/usb-solar-6w-sunpower)\n\n### 12v 100W Solar Panel Kit with Charge Controller, Sealed 55ah Battery, Mounting & Cable\n[https://www.bimblesolar.com/offgrid/complete-packages/12v-100w-pwm-sealed-complete-kit](https://www.bimblesolar.com/offgrid/complete-packages/12v-100w-pwm-sealed-complete-kit)\n\n### 12V 10Ah 3S 7P Li-ion Battery Case & Holder for DIY 18650\n[https://www.ebay.co.uk/itm/12V-10Ah-3S-7P-Li-ion-Battery-Case-Holder-for-DIY-18650-Powerwall-Battery-Pack/153790318656](https://www.ebay.co.uk/itm/12V-10Ah-3S-7P-Li-ion-Battery-Case-Holder-for-DIY-18650-Powerwall-Battery-Pack/153790318656)\n\n### 6x18650 Waterproof Battery Pack Storage Case Box\n[https://www.ebay.co.uk/itm/12V-10Ah-3S-7P-Li-ion-Battery-Case-Holder-for-DIY-18650-Powerwall-Battery-Pack/153790318656](https://www.ebay.co.uk/itm/12V-10Ah-3S-7P-Li-ion-Battery-Case-Holder-for-DIY-18650-Powerwall-Battery-Pack/153790318656)\n\n### A new torch\n\n## Clothing\n### Waterproof and waterproof trousers\n\n### Water proof backback or cover for my existing backpack\n\n### Waterproof bag for electronics/paper based things\n\n## Transport\n### Small trailer for my bike\n\n## Misc Survival\n### 10 x 167mg Oasis Water Purification Tablets - each tablet treats 20 litres water\n[https://www.ebay.co.uk/itm/10-x-167mg-Oasis-Water-Purification-Tablets-each-tablet-treats-20-litres-water/324100044800](https://www.ebay.co.uk/itm/10-x-167mg-Oasis-Water-Purification-Tablets-each-tablet-treats-20-litres-water/324100044800)\n\n### Military Surplus Water Filter\n[https://www.ebay.co.uk/itm/Military-Surplus-Water-Filter-Purification-Emergency-Gear-Straw-Camping-Hiking/223711540865](https://www.ebay.co.uk/itm/Military-Surplus-Water-Filter-Purification-Emergency-Gear-Straw-Camping-Hiking/223711540865)\n\n### Candles\n\n### Refillable lighters\n\n## Navigation\n### Compass\n### Map of UK\n### Map of my city","created":"20200318202553421","modified":"20200421010452265","tags":"Solarpunk Tech"},
{"title":"Borg Backup on Android","type":"text/x-markdown","text":"> This project provides build scripts to compile borgbackup (https://github.com/borgbackup/borg) and its dependencies on Android. It uses termux (https://termux.com/) as a lightweight environment.\n\nhttps://github.com/ravenschade/borgbackup_on_android","created":"20200716123751554","modified":"20200716123851519","tags":"Tech"},
{"title":"Borgbackup on Android","type":"text/x-markdown","text":"I used borgbackup for my personal files and for work. I'd love to get it running on Android. Haven't tested this solution yet or the Termux package but I'd like to.\n\nhttps://github.com/ravenschade/borgbackup_on_android","created":"20200817123812216","modified":"20200817123925726","tags":"Tech"},
{"title":"Bread Recipes","type":"text/x-markdown","text":"I have been making bread during lockdown. It's super fun and satisfying and then you actually get to eat the thing you made. However, my bread machine is now tripping all the fuses so I'm having to go for more of a labour intensive strategy's. I'll collect some recipes I have tried or are going to try here. \n\n## Slow cooker recipe \nPlain flour, slow cooker, kneading\n\n[https://cookingonabootstrap.com/2019/01/11/slow-cooker-bread-recipe/](https://cookingonabootstrap.com/2019/01/11/slow-cooker-bread-recipe/)","created":"20200326210256029","modified":"20200327162202827","tags":"Food"},
{"title":"Broadcasting using autistici.org","type":"text/x-markdown","text":"- https://www.autistici.org/docs/stream-obs\n- https://live.autistici.org/stats\n- https://github.com/arut/nginx-rtmp-module\n- https://obsproject.com/\n\nautistci is a radical tech collective who offer live streaming via nginx rtmp module.","created":"20201223011304740","modified":"20201223011507343","tags":"Tech"},
{"title":"Browser Stack","type":"text/x-markdown","text":"https://www.browserstack.com/\n\n> Give your users a seamless experience by testing on 2000+ real devices and browsers. Don't compromise with emulators and simulators.\n\nProprietary SASS platform that was recommended for testing apps on different browsers.","created":"20210109171122313","modified":"20210109171217724","tags":"Tech"},
{"title":"Casio Baby-G BGX-240V-4 Series","type":"text/x-markdown","text":"May have just got a vintage Casio watch. Hopefully it can help me with time management. So little info about it online.\n\nhttps://casiofanmag.com/baby-g/bgx-240v-4/","created":"20200902122229180","modified":"20200902122315472","tags":"Care Tech"},
{"title":"CBM 8032 AV computer graphics and sound 2016-2019","type":"text/x-markdown","text":"> The CBM 8032 AV project is an exploration of the beauty of simple graphics and sound, using computers from the early 1980s. This work is about the ambivalence between a contemporary aesthetic and the usage of obsolete and limited technology from 40 years ago. Everything presented within the project could have been done already in the 1980, but it needed the cultural backdrop of today to come up with the artistic ideas driving it.\n> \n> When artists began to explore computers as medium in the 1950s, technology was limited and the resulting minimalism in expression was a necessity. Half a century later, teams of thousands of programmers work on high-end games and movies, utilising clusters of the fastest computers available. The sight of a green cathode ray tube display once was the promise of an exciting future, now it is nostalgic. \n\nhttp://roberthenke.de/concerts/cbm8032av.html","created":"20200920101154296","modified":"20200920101252974","tags":"Tech Music"},
{"title":"ClamAV antivirus on Debian based systems","type":"text/x-markdown","text":"I had to fund a tutorial because I can never remember the command to update the virus definitions.\n\nhttps://linuxhint.com/install_clamav_ubuntu/","created":"20200817144826874","modified":"20200817144939640","tags":"Tech Security"},
{"title":"Community Accountability","type":"text/x-markdown","text":"Community project tackling sexual violence in a leftist community.\n\n> Taking collective responsibility against sexualised violence\n\nhttps://commacct.uber.space/","created":"20200817123652286","modified":"20200817124011644","tags":"Care Organising Social"},
{"title":"Contact tracing","type":"text/x-markdown","text":"- https://f-droid.org/en/packages/com.apozas.contactdiary/\n- https://github.com/apozas/contactdiary\n\n> Contact Diary is a simple app that allows you to keep a record of the people you have met and the events you have attended to recently. In the undesired event that you test positive for COVID-19, Contact Diary is a place where to quickly find who you must warn about the situation.\n","created":"20201223005207208","modified":"20201223005323116","tags":"Tech Mobile"},
{"title":"Cool bicycle site","type":"text/x-markdown","text":"https://www.jimlangley.net/index.html\n\nReally cool old school bicycle site. So much good info on here.","created":"20201201232636186","modified":"20201201232722278","tags":"Cycling"},
{"title":"Cool game: A Summers End - Hong Kong 1986","type":"text/x-markdown","text":"> A Summers End - Hong Kong 1986 is a visual novel game for PC. Follow the story of Michelle and Sam, and how their chance meeting evolves into a deeper romantic relationship. Set in vibrant Hong Kong in the year 1986, it is an original story about love, family, and culture.\n>\n> A Summer's End - Hong Kong 1986 is about seeking identity and meaning in a rapidly changing world where conflicting world views and cultures collide. Inspired by Hong Kong cinema, 80s anime, city pop, and contemporary Asian literature, A Summers End - Hong Kong 1986 is an homage to the past and a visual delight for fans of retro art and fashion.\n\nhttps://oracleandbone.itch.io/a-summers-end","created":"20201211140019953","modified":"20201211140106801","tags":"Gaming"},
{"title":"Cool Music","type":"text/x-markdown","text":"This is going to be such a link dump. There's so much good music out there. I will focus on independant artists or generally more obscure music.\n\n## Jessie Williams\n- https://invidious.snopyta.org/watch?v=DMXVkW27aps\n- http://jessiewilliams.bandcamp.com/\n- https://guttertown.bandcamp.com\n\n## Maya Tavener\nhttps://mayatavener.bandcamp.com/releases\n\n## Casper Allen\nhttps://casperallen.bandcamp.com/\n\n## Geoff Berner\n- https://invidious.snopyta.org/watch?v=ep7bX02Wbvg\n- https://invidious.snopyta.org/watch?v=Ps5l1DFzpUk\n- https://geoffberner.bandcamp.com/music\n- https://www.youtube.com/watch?v=2YMQQp6w98c\n\n## What You Need (feat. Duane Harden) (Lenny Fontana's Mix)\nhttps://www.youtube.com/watch?v=LCBxQget9cI\n\n## Kid Crème - Hypnotising (Original Mix) (2003)\nhttps://www.youtube.com/watch?v=JJ1xYH5j3Lk\n\n## gong - You (2016 Re-creation)\nhttps://invidious.snopyta.org/watch?v=8uNOrvvcKKk\n\n## Daniel Kahn & The Painted Bird - Dumai\nhttps://invidious.snopyta.org/watch?v=qRrknjO-whI\n\n## Dog And Fox - Who Gets The Cows?\nhttps://invidious.snopyta.org/watch?v=vCyGiwmqNXA&dark_mode=true\n\n## Bread Machine\nhttps://breadmachine.bandcamp.com/\n\n## Discostan\nhttps://soundcloud.com/discostan\n\n## Rib Fest Records\nhttps://ribfestrecords.bandcamp.com/\n\n## Charmpit\nhttps://charmpit.bandcamp.com/\n\n## Karl Biscuit\n- Karl Biscuit - \"La Morte\" - https://www.youtube.com/watch?v=R3UJv-_eDkY\n\n## Jimmy J & Cru L T\n- Jimmy J & Cru L T - I Want To Be Forever - https://www.youtube.com/watch?v=uC7MMyhV4XE\n- Jimmy J & Cru-L-T -- Take Me Away - https://www.youtube.com/watch?v=Idziyl9emjU","created":"20200429123118374","modified":"20200902121044542","tags":"Music"},
{"title":"Cool Orgs","type":"text/x-markdown","text":"Here I will keep a list of organisations that implement structures or practices that I find interesting. I may or may not add notes as I find out more about them.\n\n## Crisp DNA (Stockholm)\n[https://dna.crisp.se/docs/index.html](https://dna.crisp.se/docs/index.html)\n\n## Space4 (London)\nhttps://space4.tech/\n\n## Cooperation Birmingham\n[https://cooperationbirmingham.org.uk/](https://cooperationbirmingham.org.uk/)\n\n## Pirate Care\n[https://syllabus.pirate.care/](https://syllabus.pirate.care/)\n\n## Hacker Farm (Japan)\nhttps://hackerfarm.jp/","created":"20200327162136810","modified":"20200724122803686","tags":"Organising Social"},
{"title":"Cool phone, laptop hack","type":"text/x-markdown","text":"I thought this was a nice DIY laptop mod using old smartphones.\n\nhttps://invidious.snopyta.org/watch?v=mciEZKSvva8","created":"20200727201550296","modified":"20200727201628604","tags":"Tech"},
{"title":"Coreboot images for the Thinkpad X230","type":"text/x-markdown","text":"https://github.com/merge/skulls\n\n> pre-built coreboot images and documentation on how to flash them for the Thinkpad X230 ","created":"20201223004819202","modified":"20201223004858740","tags":"Tech"},
{"title":"Cyberpunk Clothing on Etsy","type":"text/x-markdown","text":"There's some pretty cool clothes available if you search \"Cyberpunk\" on Etsy. This is what I found with a brief search (links may die):\n\n## 2020-09-02\n- https://www.etsy.com/uk/listing/770944746/cyber-gang-cyberpunk-long-sleeve-t-shirt\n- https://www.etsy.com/uk/listing/786556029/face-off-cyberpunk-short-sleeve-t-shirt\n- https://www.etsy.com/uk/listing/776593233/geisha-20-cyberpunk-manga-japan\n- https://www.etsy.com/uk/listing/828650821/akira-motorbike\n- https://www.etsy.com/uk/listing/649577326/cyberpunk-pill-unisex-jersey-teeyami\n- https://www.etsy.com/uk/listing/814798652/akira\n- https://www.etsy.com/uk/listing/742982588/cyberpunk-sleeve-with-pocket-wasteland\n- https://www.etsy.com/uk/listing/844404206/serial-experiments-lain-t-shirt-movie\n- https://www.etsy.com/uk/listing/843011521/beach-hooded-poncho-made-from-towel\n- https://www.etsy.com/uk/listing/815016393/handmade-techwear-style-longline-hoodie\n- https://www.etsy.com/uk/shop/RagsbyJak\n- https://www.etsy.com/uk/listing/805668463/handmade-techwear-black-hoodie-with\n- https://www.etsy.com/uk/listing/292241347/new-cardigan-oversize-black-midi-sleeve\n- https://www.etsy.com/uk/listing/783973622/mens-carrot-fit-tapered-cargo-trousers\n- https://www.etsy.com/uk/listing/731767260/avant-garde-pants-cargo-pants-steampunk\n- https://www.etsy.com/uk/listing/745289056/radcliffe-mens-organic-cotton-slim-fit\n\n## 2020-09-03\n- https://www.etsy.com/uk/listing/702436670/green-alien-face-adult-hat-toy-story\n- https://www.etsy.com/uk/listing/725981466/air-japan-bomber-jacket-lightweight\n- https://www.etsy.com/uk/listing/562590411/sad-boy-long-sleeve-t-shirt\n- https://www.etsy.com/uk/listing/280551750/n64-long-sleeve-t-shirt\n- https://www.etsy.com/uk/listing/770198332/playstation-japanese-long-sleeve-t-shirt\n- https://www.etsy.com/uk/listing/587991099/linux-skirt\n- https://www.etsy.com/uk/listing/684994315/evil-corp-mens-t-shirt-unisex-cool-mr\n- https://www.etsy.com/uk/listing/670357024/hackers-movie-cyberdelia-new-york-t\n- https://www.etsy.com/uk/listing/684125827/hackers-movie-hack-the-planet-t-shirt\n- https://www.etsy.com/uk/listing/670279228/hackers-movie-angelina-jolie-acid-burn\n- https://www.etsy.com/uk/listing/768450030/planned-obsolescence\n\n## 2020-09-04\n- https://www.etsy.com/uk/listing/850776952/streetwear-techwear-joggers-matte-black\n- https://www.etsy.com/uk/listing/847628593/techwear-streetwear-harem-pants-for-men\n- https://www.etsy.com/uk/shop/Niepce\n- https://www.etsy.com/uk/listing/837936293/streetwear-joggers-men-techwear-pants\n- https://www.etsy.com/uk/listing/824046362/streetwear-japanese-kanji-embroidery\n- https://www.etsy.com/uk/listing/827857495/techwear-harajuku-matte-black-tee","created":"20200902192739022","modified":"20200904115947011","tags":"Care"},
{"title":"Cycle.travel - Cycle mapping and routing","type":"text/x-markdown","text":"I found out about cycle.travel on [this podcast](https://thebikeshow.net/planning-your-next-bike-adventure/) with the owner. He's a Open Street Map community member. I've tried it for a bikepacking trip and it went really well. Highly recommend.\n\nhttps://cycle.travel/map","created":"20200817124857741","modified":"20200817125136358","tags":"Tech Ecology"},
{"title":"Cycling trips using Ferries","type":"text/x-markdown","text":"https://www.cyclinguk.org/article/guide-taking-bike-ferry\n\n> As a sea faring nation, it only makes sense for the UK's cyclists to combine cycling with a ferry trip. With this simple guide Cycling UK's Sam Jones provides some tips on what to expect and where you can travel with your bike. ","created":"20210109172925281","modified":"20210109173002184","tags":"Travel Cycling"},
{"title":"David Bowie meets Tricky","type":"text/x-markdown","text":"I've been getting really into Tricky at the moment. I found this really odd piece by David Bowie from Q magazine (October 1995). It's a whirlwind read.\n\n> Hey! When you commission David Bowie to go see, maybe talk to trip hop ingénu Tricky, you don't expect the standard Q piece. You except a bizarre, semi-poetic fantasy written in Burgess-like futurespeak in which the Dame and the Trickster, erm, climb up the side of a tall building... don't you? Don't you? Strap yourself in, then: protein pill and helmet combination once again essential. Invoice to the usual address, Dave...\n\nhttp://www.moon-palace.de/tricky/q95.html","created":"20200817125517942","modified":"20200817125704746","tags":"Music"},
{"title":"De-Googling an Android phone","type":"text/x-markdown","text":"Here are some adb commands to disable Google packages on Android. Beware that this could break stuff. Thanks to aig on Scuttlebutt and people on the [Fairphone forum](https://forum.fairphone.com/t/google-apps-keep-reinstalling-reactivating/53563/21).\n\n```\n# list installed packages on the phone\nadb shell pm list packages\n\n# disable/uninstall a package for the main user\nadb shell pm uninstall -k --user 0 \u003Cpackage-name>\n\n# re-install a package that was previously uninstalled\nadb shell cmd package install-existing \u003Cpackage-name>\n```","created":"20201223131617009","modified":"20201223131743632","tags":"Mobile Tech"},
{"title":"Debian non-free live images","type":"text/x-markdown","text":"https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/10.7.0-live+nonfree/amd64/bt-hybrid/","created":"20201223005016943","modified":"20201223005037647","tags":"Tech"},
{"title":"Debian security software","type":"text/x-markdown","text":"- AppArmour\n- https://manpages.debian.org/testing/apt-listbugs/apt-listbugs.1.en.html\n- https://packages.debian.org/stable/debsums\n- https://wiki.debian.org/DebianSecurity/debsecan\n- https://cisofy.com/lynis/","created":"20210109173227314","modified":"20210109173317128","tags":"Security Tech"},
{"title":"Dervla Murphy","type":"text/x-markdown","text":"Amazing person who cycled from Ireland to India in 1963.\n\n> Rereading Murphys masterpiece showed me not only that this attitude has remained fairly constant for fifty years (and probably much longer), but also that it is completely unfounded. Dervla Murphy proved once and for all that gender was no encumbrance to long-distance cycling. As well as amorous suitors, she fought off packs of wolves and bandits with her .25 pistol, suffered heatstroke, dysentery and broken ribs, was bitten by scorpions, smoked, drank and swore like a trooper, and covered greater daily distances than I often do, riding a singlespeed bicycle and wearing woollen underpants (by which I assume she does not mean the latest advances in technical merino). It is only our prevailing belief that women are weaker, less resourceful, and more vulnerable, that continues to stand in our way.\n\nhttps://www.travelbooks.co.uk/dervla-murphy/\nhttps://www.apidura.com/journal/the-overlander/","created":"20200902121633194","modified":"20200902121834350","tags":"Cycling Sports"},
{"title":"Dialetical Football","type":"text/x-markdown","text":"## How 3-sided football works\nhttps://invidious.snopyta.org/watch?v=EzbnKQKszm4&dark_mode=true","created":"20200614201450442","modified":"20200614201549240","tags":"Social"},
{"title":"Dib's Fitness","type":"text/x-markdown","text":"https://www.dibsfitness.com/\n\n> Dibs is my name, and inclusive, accessible fitness is my game. I'm part of the rebellion that's taking on the health and fitness industry right now. The folks who are reclaiming exercise as fun, social, self care, and accessible to all! If you're seeking to heal your relationship with your body and with movement, or if you're after fresh inspiration on your fitness journey, I'm here for you.","created":"20210109172514321","modified":"20210109172723699","tags":"Organising Care"},
{"title":"DNS rebinding attack","type":"text/x-markdown","text":"> DNS rebinding is a method of manipulating resolution of domain names that is commonly used as a form of computer attack. In this attack, a malicious web page causes visitors to run a client-side script that attacks machines elsewhere on the network. In theory, the same-origin policy prevents this from happening: client-side scripts are only allowed to access content on the same host that served the script. Comparing domain names is an essential part of enforcing this policy, so DNS rebinding circumvents this protection by abusing the Domain Name System (DNS). \n\nhttps://en.wikipedia.org/wiki/DNS_rebinding","created":"20201201224936279","modified":"20201201225016478","tags":"Tech"},
{"title":"Early Cyberpunk","type":"text/x-markdown","text":"http://www.infinityplus.co.uk/stories/cpunk.htm\n\n> In the early spring of 1980 I wrote a little story about a bunch of teenage hackers. From the very first draft this story had a name, and lo, the name was CYBERPUNK!\n\nEarly cyberpunk story.\n","created":"20201223002427420","modified":"20201223002518377","tags":"Books Writing"},
{"title":"EARTHEART by YaYa Bones","type":"text/x-markdown","text":"> YaYa Bones is the musical alter ego of artist Ayesha Tan Jones.\nThey make protest music for witches, technological opera, and dream n bass.\n\nhttps://yayabones.bandcamp.com/\n\nNew E.P by a friend of mine. My fav track is Tender Muscles.\n","created":"20201211140325016","modified":"20201211140423134","tags":"Music"},
{"title":"Ecology","text":"","color":"#efeaff","created":"20200321185009422","modified":"20200321232552113"},
{"title":"Elite Panic","type":"text/x-markdown","text":"> Attributions of panic are almost exclusively directed at members of the general public. Here, we inquire into the relationships between elites and panic. We review current research and theorizing about panic, including problems of identifying when it has occurred. We propose three relationships: elites fearing panic, elites causing panic and elites panicking. We use numerous examples, including our own research on the 2001 anthrax attacks in the United States, to illustrate how these relationships operate. The argument is evocative, not definitive. However, the conceptual utility of explicitly theorizing the relationships between elites and panic shows, among other things, how power works in disasters.\n\n- https://www.iheart.com/podcast/105-behind-the-bastards-29236323/episode/elite-panic-why-the-rich-and-74157341/\n- https://www.jstor.org/stable/20430900?seq=1\n- https://www.commentarymagazine.com/articles/james-meigs/elite-panic-vs-the-resilient-populace/\n- https://link.springer.com/referenceworkentry/10.1007%2F978-3-319-31816-5_3544-1\n- \n\n## Definitions\n### Disaster myths:\n Common misconceptions about disasters and disaster behavior\n\n### Panic:\n Irrational emotional and/or behavioral responses triggered by sudden strong feelings of fear and/or anxiety\n\n### Elite panic:\n Inappropriate disaster response by persons and/or organizations in positions of authority who panic about the possibility of panic among the general public\n\n## References\n\n Clarke L, Chess C (2008) Elites and panic: more to fear than fear itself. Soc Forces 87(2):9931014. https://doi.org/10.1353/sof.0.0155 CrossRefGoogle Scholar\n \n\n Nogami T (2016) Who panics and when: a commonly accepted image of disaster panic in Japan. Int Perspect Psychol: Res Pract Consult 5(4):245255. https://doi.org/10.1037/ipp0000050 Google Scholar\n\n Quarantelli EL (2001) The sociology of panic. In: Smelser NJ, Baltes PB (eds) International encyclopedia of the social and behavioral sciences. Elsevier Science Ltd., Oxford, pp 1102011023CrossRefGoogle Scholar","created":"20201201223544985","modified":"20201220165308197","tags":"Psychology Organising"},
{"title":"Enkindle Village School Case Study","type":"text/x-markdown","text":"Case study about a democratic school:\n\nhttps://www.sociocracyforall.org/enkindle-casestudy/","created":"20200724122227606","modified":"20200724122326941","tags":"Ecology Organising"},
{"title":"Estonia E-Residency and Digital Nomad Visa","type":"text/x-markdown","text":"https://e-resident.gov.ee/nomadvisa/","created":"20210109171005933","modified":"20210109171109379","tags":"Travel Tech"},
{"title":"Excellent Cycle Mapping site","type":"text/x-markdown","text":"It also has guides.\n\nhttps://cycle.travel/","created":"20200724122642969","modified":"20200724122727469","tags":"Care Ecology"},
{"title":"Exiting The Vampire Castle by Mark Fisher","type":"text/x-markdown","text":"Mark Fisher\n22-28 minutes readtime\n\nEssay about social media and the left.\n\nhttps://www.opendemocracy.net/en/opendemocracyuk/exiting-vampire-castle/","created":"20200716124057097","modified":"20200716124148557","tags":"Organising Tech"},
{"title":"Fair Ferry","type":"text/x-markdown","text":"https://www.fairferry.co.uk/\n\nCool wind powered cruises.\n\n> Something new or perhaps something old and long forgotten? A ferry service by sailing ship. Sustainable? For sure. An adventure? You bet! That's Fair Ferry and its tall ships. Because we believe the journey should be every bit as memorable and enjoyable as the destination itself.","created":"20220414221928106","modified":"20220414222001945","tags":"Ecology Travel"},
{"title":"Flash Fiction","type":"text/x-markdown","text":"> Flash fiction is a fictional work of extreme brevity[1] that still offers character and plot development. Identified varieties, many of them defined by word count, include the six-word story;[2] the 280-character story (also known as \"twitterature\");[3] the \"dribble\" (also known as the \"minisaga,\" 50 words);[2] the \"drabble\" (also known as \"microfiction,\" 100 words);[2] \"sudden fiction\" (750 words);[4] flash fiction (1,000 words); and \"micro-story\".\n\nhttps://en.wikipedia.org/wiki/Flash_fiction","created":"20201201225231123","modified":"20201201225301099","tags":"Writing"},
{"title":"Foraging Recipes","type":"text/x-markdown","text":"Recipes I have made using produce foraged from my local area.\n\n## Wild Garlic\n### Nut-Free Wild Garlic Pesto\nhttps://www.onegreenplanet.org/vegan-recipe/nut-free-wild-garlic-pesto/","created":"20200401123422858","modified":"20200401123646301","tags":"Solarpunk Ecology Food"},
{"title":"From Managerial Feudalism to the Revolt of the Caring Classes","type":"text/x-markdown","text":"Excellent David Graeber talk from 36c3 which I saw in person. Great analysis and conclusions. I keep coming back to this.\n\n> One apparent paradox of the digitisation of work is that while productivity in manufacturing is skyrocketing, productivity in caring professions (health, education) is actually declining - sparking a global wave of labour struggle. Existing economic paradigms blind us to understanding how economies have come to be organised. We meed an entirely new discipline, based on a different set of values.\n\nhttps://media.ccc.de/v/36c3-11241-from_managerial_feudalism_to_the_revolt_of_the_caring_classes","created":"20200817125327687","modified":"20200817125502978","tags":"Care Organising Social"},
{"title":"Game Engines","type":"text/x-markdown","text":"I really want to try making a small simple solarpunk game. I'm going to collect some libre gaming engines here to investigate. I'd love something that runs in the browser and can be downloaded by saving the web page locally.\n\n## Bitsy\n- https://ledoux.itch.io/bitsy\n- https://github.com/le-doux/bitsy\n- https://www.shimmerwitch.space/bitsyTutorial.html\n- https://itch.io/games/made-with-bitsy\n- https://itch.io/t/147202/adding-a-soundmusic-assets-to-a-bitsy-game\n- https://candle.itch.io/bitsy-audio\n\n### Borksy\n- https://ayolland.itch.io/borksy\n- https://github.com/Ayolland/borksy\n\n## Solarus\n- https://www.solarus-games.org/en/solarus/overview\n\n## Ren'Py\nThis is more of a visual novel engine.\n- https://www.renpy.org/\n- https://www.renpy.org/doc/html/index.html\n\n## RPG In a Box\nRPG in a Box lets you easily create 3D grid-based, voxel-style RPGs and adventure games\n- https://www.rpginabox.com/\n\n## GB Studio\nMake Gameboy Colour style games.\n- https://github.com/chrismaltby/gb-studio\n- https://www.gbstudio.dev/\n- https://chrismaltby.itch.io/gb-studio","created":"20200606112657799","modified":"20200826122355013","tags":"Tech"},
{"title":"Garden diaries 20.3.20","type":"text/x-markdown","text":"Ive been trying to do more in the garden during self isolation. Inspired by Nicole Rose's excellent booke *The Prisoner's Herbal* I have been learning to prepare and eat/drink nettles and dandelions. I've been trying to learn one of the plants in the book and then go out and see if I can find it in the garden. It's Plantain next.\n\n## Harvested\n* Oyster mushrooms\n* Nettle leaves\n* Dandelion leaves\n\n## Other work\n* Mulched some beds with our home made compost\n* Freed up space for a new compost bin\n* Removed horrible plastic from green house structure\n* Litterpicked our back garden, front garden and a bit of the neighbours abandoned garden\n \n## Nettle recipe \n- Pick (with gloves)\n- Wash \n- Infuse in boiling water (either 10 mins or overnight) and then treat as you would spinach\n- Liquid from infusion can be drunk as tea\n\n## Dandelions\n- Pick\n- Wash\n- Eat raw or make an infusion as with nettles\n\n## Update\nIt turns out a nettle/dandelion infusion left overnight and then reheated is incredibly tasty to drink! No sugar or anything needed.","created":"20200320214156031","modified":"20200321181825018","tags":"Solarpunk Ecology"},
{"title":"Garden Diaries 21.3.20","type":"text/x-markdown","text":"It turns out a nettle/dandelion infusion left overnight and then reheated is incredibly tasty to drink! No sugar or anything needed. Check my previous garden diary for more details.\n\nI also picked a bunch of [wild garlic](https://en.wikipedia.org/wiki/Allium_ursinum) today. It's totally in season (April to June in UK) so get out there and collect it! If you're not sure if you've ID'd it right, just break and leave and mash up a little and you'll know but check the wiki article for more info on this.\n\nIt probably won't last for more than three or four days once picked so I may attempt to freeze some as we have space in the freezer.\n\nI also made [saurkraut](https://en.wikipedia.org/wiki/Sauerkraut) last night as well with our surplus of cabbage. Trying to find lots of ways to store stuff and increase my foraging knowledge. \n\n## Harvested \n- Wild garlic\n","created":"20200321181843921","modified":"20200324010648362","tags":"Solarpunk Ecology"},
{"title":"Garden diaries 23.3.20","type":"text/x-markdown","text":"Lounged in the garden quite a bit. Did some Muay Thai rounds on the heavy bag. I need to be training every day really to keep the isolation blues away.\n\n## Harvested \n- One lone potato\n\n## Planted\n- Planted strawberries in the mini greenhouse thing\n- Spread the \"ice plant\" seeds from last year in various spots around the garden\n- Planted some sprouting potatoes in an old bin\n\n## Other Work\n- Weeded one bed\n- More litterpicking\n","created":"20200323162812820","modified":"20200324003743958","tags":"Solarpunk Ecology"},
{"title":"GDS pre commit - Prevent commiting secrets to git repos","type":"text/x-markdown","text":"> An easy-to-install git precommit hook for preventing potential secrets being committed to git \n\nhttps://github.com/alphagov/gds-pre-commit","created":"20200817131158733","modified":"20200817131257885","tags":"Tech"},
{"title":"Gideon the Ninth (The Locked Tomb #1)","type":"text/x-markdown","text":"Recommended by Soapdog.\n\n> The Emperor needs necromancers.\n>\n> The Ninth Necromancer needs a swordswoman.\n>\n> Gideon has a sword, some dirty magazines, and no more time for undead bullshit.\n\nhttps://www.goodreads.com/book/show/42036538-gideon-the-ninth","created":"20201201225055802","modified":"20201201225154216","tags":"Queer Books"},
{"title":"git-ssb","type":"text/x-markdown","text":"git-ssb is a P2P implementation of git. It's quite hard to install though so I am just storing some links here to come back to when I have more spoons.\n\n- https://git.scuttlebot.io/%25n92DiQh7ietE%2BR%2BX%2FI403LQoyf2DtR3WQfCkDKlheQU%3D.sha256\n- https://git.scuttlebot.io/%25iqhz%2FsQCZCSp91JYAqfQPzHuDYrjw1geKPf1wJ1CvlA%3D.sha256\n- http://git.scuttlebot.io/%25VaSj08AbdhIa4itK4z8Z91G80o2h5OhRLCEEO6MhAcU%3D.sha256\n- https://git.scuttlebot.io/%25YAg1hicat%2B2GELjE2QJzDwlAWcx0ML%2B1sXEdsWwvdt8%3D.sha256","created":"20200624230451039","modified":"20200624230726228","tags":"Tech P2P"},
{"title":"Glitter + Ashes: Queer Tales of a World That Wouldn't Die","type":"text/x-markdown","text":"My friend [Otter Lieffe](https://otterlieffe.com/) has a short story in this queer Solarpunk/speculative queer fiction anthology. I want to read it so bad.\n\n> Glitter + Ashes: Queer Tales of a World That Wouldnt Die is an anthology of post-apocalyptic fiction centering queer joy and community in the face of disaster. What does hope look like when everything is lost? Now, more than ever, we need to revel in the bright spots amidst the darkness.\n> \n> The twenty-three stories (and two poems) contained here, as well as the roleplaying game Dream Askew by Avery Alder, imagine queer community in myriad futures interrupted by collapse. Post-apocalyptic futures glittering and bleak, challenging and eerie.\n> \n> Glitter + Ashes is here to hold up a torch. Come gather round the fire.\n>\n> Coming September 2020. Cover by Grace Fong. ","created":"20200817130315825","modified":"20200817130526436","tags":"Solarpunk Books"},
{"title":"GNOME break timer","type":"text/x-markdown","text":"https://flathub.org/apps/details/org.gnome.BreakTimer\n\nRecommended by a friend.","created":"20201223004915265","modified":"20201223005002210","tags":"Care Organising Tech"},
{"title":"GNOME circles","type":"text/x-markdown","text":"> Applications and libraries extending the GNOME ecosystem.\n\n> GNOME Circle champions the great software that is available for the GNOME platform. Not only do we showcase the best apps and libraries for GNOME, but we also support independent developers who are using GNOME technologies. \n\nhttps://circle.gnome.org/","created":"20210109172256200","modified":"20210109172323819","tags":"Tech"},
{"title":"GNOME terminal keyboard shortcuts","type":"text/x-markdown","text":"https://help.gnome.org/users/gnome-terminal/stable/adv-keyboard-shortcuts.html.en","created":"20201223005917567","modified":"20201223005931567","tags":"Tech"},
{"title":"Google Pixel 3a Repair Guide","type":"text/x-markdown","text":"Here is the ifixit guide for the Pixel 3a:\n\nhttps://www.ifixit.com/Device/Google_Pixel_3a\n\nIt doesn't look so bad but it is all glued together.","created":"20201211135432254","modified":"20201211135546621","tags":"Tech Mobile"},
{"title":"Graphene OS","type":"text/x-markdown","text":"https://grapheneos.org/\n\n```\nGrapheneOS is an open source privacy and security focused mobile OS with Android app compatibility. It's focused on the research and development of privacy and security technology including substantial improvements to sandboxing, exploit mitigations and the permission model. GrapheneOS also develops various apps and services with a focus on privacy and security. Vanadium is a hardened variant of the Chromium browser and WebView specifically built for GrapheneOS. GrapheneOS also includes our minimal security-focused PDF Viewer, our hardware-based Auditor app / attestation service providing local and remote verification of devices, and the externally developed Seedvault encrypted backup which was initially developed for inclusion in GrapheneOS.\n```\n\n## Attestation app\nThis looks really interesting.\n\nhttps://attestation.app/\nhttps://play.google.com/store/apps/details?id=app.attestation.auditor","created":"20201203140810835","modified":"20201203140927182","tags":"Security Tech Mobile"},
{"title":"Great DJ Mixes","type":"text/x-markdown","text":"## https://soundcloud.com/dj-jo-public\n- https://soundcloud.com/dj-jo-public/sets/ltj-bukem-dj-mixes-studio-sets","created":"20200902120844654","modified":"20200902120912411","tags":"Lists Music"},
{"title":"Gridsound: DAW in the browser","type":"text/x-markdown","text":"I suspected it was possible but I've not seen a great browser base DAW. This awesome libre project has made a great start.\n\nhttps://gridsound.com/daw/\nhttps://github.com/gridsound/daw\nhttps://hackaday.com/2020/08/17/gridsound-an-audio-workstation-in-your-browser/","created":"20200817123350782","modified":"20200817123517638","tags":"Tech Music"},
{"title":"Habits - Habit tracking","type":"text/x-markdown","text":"https://f-droid.org/en/packages/org.isoron.uhabits/\n\n> Loop is a simple app that helps you create and maintain good habits, allowing you to achieve your long-term goals. Detailed graphs and statistics show you how your habits improved over time.","created":"20201223005123123","modified":"20201223005226808","tags":"Tech Mobile"},
{"title":"Hackers Curator Fan Site","type":"text/x-markdown","text":"Incredibly thorough fan community for the awesome 1995 film Hackers. I love all the research on the clothes and gadgets.\n\nhttps://hackerscurator.com","created":"20200919201502483","modified":"20200919201605281","tags":"Films Tech"},
{"title":"Half Barges - Canal Boats","type":"text/x-markdown","text":"After a convo with a friend, I've starting looking at boats even though I am the most landlubber person ever.\n\nI really like this half barge format of canal boats. I bet they're so much easier to manoeuvrer. \n\nhttps://narrowboats.apolloduck.co.uk/boat/hallmark-25-cruiser-stern/640596/4388604\nhttps://narrowboats.apolloduck.co.uk/boat/hirst-boat-builders/615111","created":"20200709135427165","modified":"20200709135650683","tags":"Ecology Social"},
{"title":"HAM Radio Resources","type":"text/x-markdown","text":"A place to collect resources that have been useful when learning more about ham radio \n\n## Training courses\n- [https://www.essexham.co.uk/train/foundation-online/](https://www.essexham.co.uk/train/foundation-online/\n)\n- [https://www.essexham.co.uk/train/coronavirus/](https://www.essexham.co.uk/train/coronavirus/\n)\n\n## Analysis\n- [https://hackaday.com/2016/12/12/my-beef-with-ham-radio/](https://hackaday.com/2016/12/12/my-beef-with-ham-radio/\n)\n\n## YouTube Channels\n- Ringway Manchester\n- HAM Radio Crash Course\n\n## Online Software Defined Radios\n- [http://websdr.org/](http://websdr.org/)\n\n## Radio Society of Great Britain\n- [https://rsgb.org/main/](https://rsgb.org/main/)\n- [https://rsgb.org/main/operating/licensing-novs-visitors/uk-licensing/](https://rsgb.org/main/operating/licensing-novs-visitors/uk-licensing/)\n\n## How To guides\n- [https://warlord0blog.wordpress.com/2017/05/11/setting-up-baofeng-uv-5r-for-pmr-446/](https://warlord0blog.wordpress.com/2017/05/11/setting-up-baofeng-uv-5r-for-pmr-446/)\n\n## Topics \n### CTCSS/DCS\n- [https://en.wikipedia.org/wiki/Continuous_Tone-Coded_Squelch_System](https://en.wikipedia.org/wiki/Continuous_Tone-Coded_Squelch_System)\n- [https://radiosification.blogspot.com/2013/12/what-is-ctcss-and-dcs.html](https://radiosification.blogspot.com/2013/12/what-is-ctcss-and-dcs.html)\n\n### Repeaters\n- Download UK repeater info - https://www.m0lxq.com/repeater/\n- Repeater 101 for new Amateur Radio Operators - https://invidious.snopyta.org/watch?v=TNxyfRDpwpA\n- Ham Radio Basics - Making Your First Contact on a Repeater - https://invidious.snopyta.org/watch?v=SGyS81QSl6U\n\n### PMR 446 - Walkie Talkies\n- https://en.wikipedia.org/wiki/PMR446\n\n### Slang\n- https://en.wikipedia.org/wiki/Maidenhead_Locator_System\n- https://en.wikipedia.org/wiki/NATO_phonetic_alphabet\n\n### Packet Radio\n- Packet Radio (Post Apocalyptic Internet?) - https://invidious.snopyta.org/watch?v=lx6cm1rNDLM","created":"20200416112737861","modified":"20200422171324574","tags":"Lists Social Tech"},
{"title":"Harrison Consoles VST Plugins","type":"text/x-markdown","text":"https://harrisonconsoles.com/ava-plugins/\n\nVST plugins that run on Linux.","created":"20201223004125877","modified":"20201223004257580","tags":"[[Music Production]]"},
{"title":"Hello World!","type":"text/vnd.tiddlywiki","text":"This is a test of hosting a TiddlyWiki on Dat.","bag":"default","created":"20200226233526335","modified":"20200307170955421","revision":"0","tags":"Tech P2P"},
{"title":"Hosting hypercore sites","type":"text/x-markdown","text":"A friend told me that [dat-store](https://github.com/datproject/dat-store/) is now a good go to for seeding hypercore sites without using [Beaker Browser](https://beakerbrowser.com/).\n\nIt's all super confusing right now because of the breaking changes and name change from Dat to Hypercore. I'll probably set this up on my server soon.\n\nhttps://github.com/datproject/dat-store/","created":"20200704194813248","modified":"20200705152416063","tags":"P2P Tech"},
{"title":"How to force the DVLA to accept your name change","type":"text/x-markdown","text":"A comrade managed to get their name changed by the [DVLA](https://www.gov.uk/government/organisations/driver-and-vehicle-licensing-agency) which is the driving license agency here in the UK.\n\n> As of the first of August, I finally have formal, government-issued identification with my name on it. It's a provisional driving license, and it cites me as 'MX - COLONS'. The 'COLONS' is embossed and everything, it's very fancy. I'd rather it didn't have a title on it at all, but I can sort that later.\n\nhttps://colons.co/words/dvla/","created":"20200817125744437","modified":"20200817125918054","tags":"Organising Social"},
{"title":"How to Use the WP-CLI Command Line Tool to Change Your WordPress Website Url or Domain","type":"text/x-markdown","text":"https://dotlayer.com/how-to-use-the-wp-cli-command-line-tool-to-change-your-wordpress-website-url-or-domain/","created":"20201201232545776","modified":"20201201232558355","tags":"Tech"},
{"title":"In the ruins of the garden (part 1)","type":"text/x-markdown","text":"# On the fediverse, co-operatives and scale\n\n## Part 1: What has happened...\n\nOn 6th March 2020, there was a huge incident on the Mastodon instance [Sunbeam.city](dat://cf9de5d87118ad22ecd927df1c1b174632c6a1920ade2ef57f75e8421017ccc5/doku.html). I'll try and give a brief outline of what happened and then move on to more meta topics. It is not known at this time, whether Sunbeam City as a Mastodon instance or as a solarpunk co-operative will continue.\n\nEssentially, the Sunbeam City co-op has been in a difficult spot for a long time, with original founder of the project leaving, we had difficulties assembling a team of volunteers in order to carry out moderation and admin duties. Nevertheless the instance kept on growing and eventually a new team was formed by trusted members of the community.\n\nAfter several incidents where moderation processes were lacking and after receiving critique from comrades in our surrounding communities, we decided to enter into a process of reform surrounding our structure and purpose. This was an important task as I feel we had been floundering, suffering from a lack of clear vision and didn't have structure in place that allowed us to make decisions effectively. \n\nIn absence of a functional decision making process (our Loomio, having been abandoned due to poor UX and lack of engagement), those that had significant knowledge of the co-operative and its history essentially made most of the decisions, seeking consensus and feedback from the rest of the co-operative using Mastodon's polls feature.\n\nDuring this time of restructuring, several mods stepped down and several new mods volunteered. This was seen as a necessary step at the time in decolonising our co-operative as we had previously had (as far as I know) a all white mod and server admin team which had caused issues in the sense of our own lack of education and understanding of racism and how it manifests on the fediverse which lead to some poor moderation decisions being made. \n\nMost of the criticism we received for our mistakes was comradely and incredibly useful and I thank them for it immensely. There is nothing more constructive than receiving critique that is thoughtful and challenges emerging power dynamics within a project especially when they relate to issues of race and class. \n\nHowever, there is always going to be a vocal minority that show a lack of empathy and forgiveness when it comes to well meaning people making mistakes. Usually these people being unkind are not the people that made the original nuanced critiques and are not interested in putting in actual work to try and resolve the issues raised. Their strategy for changing the structures around them is to just be really mean to everyone until they get their way. In my opinion this is a troublesome and childish thing to do. It interesting to note that a certain pattern emerges with these people. They are usually white and from the so called USA. Read into that what you will.\n\nThe problem with this influx of new mods, was that we were handing out very important positions to people that hadn't been around on the instance for a while and hadn't gained the trust of the co-operative. This lead to a serious issues where one member was almost made a moderator when it turned out they had been complicit in racist harassment of a comrade of ours from another instance. This member was banned but this just goes to show that you have to be constantly vigilant for harmful people and defend your structures and surrounding communities from those that seek to do harm. \n\nAgain, we were justifiably critiqued by friends and comrades. This hastened our efforts to examine the structure of the cooperative and our overall purpose. I setup a [Discourse forum](https://sunbeamcity.autonomic.zone/) on my tech co-op's infrastructure to help discussions to happen. On a recommendation, sign-ups were left open so comrades from beyond the bounds of the membership could contribute.\n\nUnfortunately, disast
{"title":"Interact with ssh agent using ssh-add","type":"text/x-markdown","text":"https://www.ssh.com/ssh/add\n\ne.g. `ssh-add ~/.ssh/tatu-aws-key`\n\nFor full info, see `man ssh-add`","created":"20201223132334492","modified":"20201223132425084","tags":"Tech"},
{"title":"Introduction to AppArmour","type":"text/x-markdown","text":"https://debian-handbook.info/browse/stable/sect.apparmor.html\n\nIntroduction to AppArmour from the Debian Handbook","created":"20210109173025152","modified":"20210109173053519","tags":"Security Tech"},
{"title":"Jenny Grahams Around the World Record Breaking Kit","type":"text/x-markdown","text":"> A closer look at Jenny Grahams around the world record-breaking kit.\n> On Thursday the 18th of October 2018, Jenny Graham made history by becoming the fastest woman to circumnavigate the world by bike. She started in Berlin on the 16th of June 2018 and returned 124 days and 29,656km later, beating the previous record by 20 days.\n> \n> Following her incredible achievement, one of the questions Jenny has most frequently been asked is “what kit did you carry to ride around the world?”. Here, Jenny exclusively gives us a closer look at what was in her packs.\n\nhttps://www.apidura.com/journal/jenny-grahams-around-the-world-record-breaking-kit/","created":"20200902121835918","modified":"20200902121932809","tags":"Cycling Sports"},
{"title":"Joining Freenode IRC channels using Matrix","type":"text/x-markdown","text":"You can join any [Freenode IRC channel](https://freenode.net/) from the more modern [Matrix network](https://matrix.org/) by joining a room with this format\n\n`#freenode_#roomname:matrix.org`\n\nFor example: `#freenode_#meetcoop:matrix.org` etc.\n\nThis allows you to use Matrix as a really good IRC bouncer for persistent IRC history alongside all the Matrix goodness. I hope other IRC networks are going to adopt this also.","created":"20200701103545627","modified":"20200701104401832","tags":"Social Tech"},
{"title":"Karl Biscuit","type":"text/x-markdown","text":"Really cool underground electronic musician.\n\nhttps://www.junodownload.com/products/karl-biscuit-aktualismus/2030715-02/\nhttps://www.discogs.com/artist/5111-Karl-Biscuit\n\n### Karl Biscuit - La Morte\nhttps://invidious.snopyta.org/watch?v=R3UJv-_eDkY\n\n### Karl Biscuit - hiérophone ( Avalon remix )\nhttps://www.youtube.com/watch?v=7fpv4o8ZaYY","created":"20200724121840585","modified":"20200724122111046","tags":""},
{"title":"KawaiiPunk","type":"text/x-markdown","text":"# Librepunk/Co-operator/Union Organiser \n\n## STATS\n* Pronouns: [They/Them](https://pronoun.is/they)\n* Makes music as: [Lai Power](https://soundcloud.com/laipower)\n* Breaks things with: [Autonomic Co-operative](https://autonomic.zone/)\n* Organises with: [IWW](https://iww.org.uk/) and [Acorn](https://acorntheunion.org.uk/)\n* Toots as: [@kawaiipunk@sunbeam.city](https://sunbeam.city/@kawaiipunk)\n* Blogs as: \n[https://kawaiipunk.xyz/](https://kawaiipunk.xyz/)\nhyper://53aef94902dcb6ec0deebb212175f0b25bd0e2c3da4bb0f32e25eba9f306a4ce/ \n\n## INTERESTS\n* Punk2Punk connections both online and IRL\n* Fully Democratic Anarchist Luxury Syndicalist Confederalism\n* Solarpunk worker co-ops and lunarpunk housing co-ops\n* Martial-arts\n* ADHD\n* Luxury librepunk software\n* Being queer as in freedom\n\n## CONTACT\n### Mastodon\n#### Main\n[@kawaiipunk@sunbeam.city](https://sunbeam.city/@kawaiipunk)\n#### Art\n[@kawaiipunk@pixelfed.social](https://pixelfed.social/kawaiipunk)\n\n### Scuttlebutt\n@LVL4qjvmws3Cxavfi4iCQI6dSOqWqOyq5/5CHImILA8=.ed25519 (Main)\n\n@aeJxL8KfBOxnGuTT/rMgKp3n3qTPW9cvLFRqRpiBSBo=.ed25519 (Manyverse/Mobile)\n\n### Matrix/Riot\n@kawaiipunk:fairydust.space\n#### Devices\nFYYCJFBWFW\n#### Fingerprint\n`tXeE hbfo nK/I wz7/ 8dCf oXM/ rUnt bobt alIh U7Jk ICo`\n\n### XMPP/OMEMO\nkawaiipunk@dismail.de\n\n`2d9164eb 7c36f3b7 d056efab 2b93f454\neda35f5f 42f85e3e 30eed1a0 3f634d7e`\n\n`c45737cc 4a0d8a 830c44e b1b92e50 3b844caa0 204b6d cfb6e22 ceeb47 5bfa4e`\n\n### Email\nEmail address on request\n\nPGP Key: \n`6F5A 77AE 4D69 64DE 627C 9B1F 8664 A690 E094 B219`\n\n### Signal\nPhone number on request\n\n## HACK THE PLANET!","created":"20200307225039939","modified":"20211216130324515"},
{"title":"Keyoxide","type":"text/x-markdown","text":"https://keyoxide.org/\nhttps://keyoxide.org/9f0048ac0b23301e1f77e994909f6bd6f80f485d\n\n\n> Keyoxide allows you to link accounts on various online services and platforms together, prove they belong to you and establish an online identity. This puts you, the internet citizen, in charge when it comes to defining who you are on the internet instead of large corporations.","created":"20210109170912734","modified":"20210109170948822","tags":"Security Tech P2P"},
{"title":"Khabat Abbas - Journalist in Rojava","type":"text/x-markdown","text":"Khabat is a very good journalist in Northern Syria. She featured on a great podcast called [The Women's War by Robert Evans](https://www.iheart.com/podcast/1119-the-womens-war-59464911/).\n\n- https://nitter.net/khabat_abas\n- https://www.stern.de/p/plus/gesellschaft/-kampf-ist-mein-name----was-es-bedeutet--als-kurdin-in-syrien-zu-leben-9070014.html","created":"20200716123327809","modified":"20200716123805397","tags":"Ecology Organising"},
{"title":"Lenovo BIOS Embedded Controller Update Vulnerability","type":"text/x-markdown","text":"https://support.lenovo.com/gb/en/solutions/len-27764\n\n> A vulnerability was reported in older ThinkPad systems that could allow a user with administrative privileges or physical access the ability to update the Embedded Controller with unsigned firmware.","created":"20210309151819977","modified":"20210309151929175","tags":"Tech"},
{"title":"Less Talk Athletics","type":"text/x-markdown","text":"Excellent leftist supplier of combat sports gear. Great quality. \n\nhttps://less-talk.com/","created":"20200902121111185","modified":"20200902121157743","tags":"Organising"},
{"title":"Libertatia: Pirates and Anarchist Utopia","type":"text/x-markdown","text":"https://en.wikipedia.org/wiki/Libertatia\n\n> Libertatia (also known as Libertalia) was a purported pirate colony founded in the late 17th century in Madagascar under the leadership of Captain James Misson.\n\n> Misson was known for his role as founder of Libertalia and the radical ideas that it represented. These radical ideas and stories that were associated with Misson resonated throughout the world, and most importantly throughout the pirate community. Misson and the rest of the pirate community were strongly opposed to the various forms of authoritarian social constructs such as monarchies, slavery, and capital. These same pirates practiced forms of direct democracies that are similar to the democracies of 21st century. \n>\n> They envisioned a society where the people as a whole held the authority to make laws and rules, and used systems of councils with elected delegates. Pirates were strong anti-capitalists, who opposed the dispossession that followed the histories ascent of wage labor and capitalism. The society that they had established was a form of direct democracy intertwined with a socialist economy. \n>\n> They believed that \"Every man was born free, and had as much right to what would support him, as to the air he respired.\" They also believed that vices of wealth created \"wretchedly miserable\" people. They spoke of the \"natural right\" to \"a share of the earth as is necessary for our support.\" They saw piracy as a war of self-preservation, which justified their actions","created":"20201201224732250","modified":"20201201224924121","tags":"History"},
{"title":"Libre x42 audio plugins","type":"text/x-markdown","text":"https://x42-plugins.com/x42/\n\n> professional audio processing units available as LV2-plugin and JACK-application","created":"20201223004308929","modified":"20201223004519385","tags":"[[Music Production]]"},
{"title":"LibreRouter","type":"text/x-markdown","text":"Not seen this router project before. Looks interesting.\n\nhttps://librerouter.org/what/","created":"20200920100834684","modified":"20200920100929218","tags":"Solarpunk Tech"},
{"title":"Linux / UNIX: DNS Lookup Command","type":"text/x-markdown","text":"https://www.cyberciti.biz/faq/unix-linux-dns-lookup-command/","created":"20201201232428016","modified":"20201201232442495","tags":"Tech"},
{"title":"Linux Kernel maintainer's PGP guide","type":"text/x-markdown","text":"https://www.kernel.org/doc/html/v5.9-rc3/process/maintainer-pgp-guide.html\n\n> PGP helps ensure the integrity of the code that is produced by the Linux kernel development community and, to a lesser degree, establish trusted communication channels between developers via PGP-signed email exchange.","created":"20210109171642095","modified":"20210109171716570","tags":"Security Tech"},
{"title":"Live Lightning Maps","type":"text/x-markdown","text":"Not sure exactly how this data is captured but these lightning maps are really cool.\n\n- https://www.lightningmaps.org/\n- https://map.blitzortung.org\n- https://www.blitzortung.org/en/live_lightning_maps.php\n","created":"20200817124445358","modified":"20200817124628071","tags":"Social"},
{"title":"Logic Mag","type":"text/x-markdown","text":"Seems like a cool magazine!\n\nhttps://logicmag.io/#issues\n\nhttps://logicmag.io/commons/inside-the-whale-an-interview-with-an-anonymous-amazonian/","created":"20210109170231635","modified":"20210109170335247","tags":"Organising Writing"},
{"title":"London Clarion Cycling Club gear","type":"text/x-markdown","text":"https://londonclarioncycleclub.bigcartel.com/products\n\nSick cycling merch. I would love to get something if I had the money.","created":"20201201223437176","modified":"20201201223605902","tags":"Sports Cycling"},
{"title":"Los Angeles rideshare drivers union","type":"text/x-markdown","text":"https://drivers-united.org/join\n\nThis union has a cool website and sign up form.","created":"20201223005331414","modified":"20201223005408593","tags":"Organising"},
{"title":"Marianne Breslauers photos of queer, androgynous and butch women of the 1930s","type":"text/x-markdown","text":"https://dangerousminds.net/comments/marianne_breslauers_gorgeous_photos_of_queer_androgynous_and_butch_women_of\n \n> The photography of Marianne Breslauer is striking for both its intimacy and its subjects—women, usually of the sleek, chic and gender-bending variety, posed to optimum androgynous elegance. A bohemian Berliner by birth, Breslauer studied under Man Ray for a time in Paris and achieved some commercial success before returning home to an increasingly volatile Germany. As a Jewish artist working in an obviously queer milieu, Breslauer eventually fled to Switzerland and retired from photography early, eventually marrying a man and becoming an art dealer.\n> \n> Among the many beautiful faces captured by Breslauer was her dear friend, Swiss writer, journalist and photographer Annemarie Schwarzenbach, who she described as “neither a man nor a woman, but an angel, an archangel.” A libertine and rebel, Schwarzenbach defied her wealthy, Nazi-sympathizing family, funding anti-fascist publications and later supporting American unions at the height of the Depression—this is not to mention her adventures hitchhiking across India and Turkey, or the many lesbian affairs. Surviving addiction issues and a suicide attempt, Schwarzenbach nonetheless died at the young age of 34 after a fall from a bicycle, leaving behind a prolific body of work, 170 articles and 50 photo-reports.","created":"20201223003048792","modified":"20201223003200027","tags":"Queer Art"},
{"title":"Matrix Fansite","type":"text/x-markdown","text":"Excellent collection of fan theories around the Matrix universe:\n\nhttps://www.matrixresolutions.com/index.html","created":"20200920094754821","modified":"20200920094841988","tags":"Films"},
{"title":"Meeting check outs","type":"text/x-markdown","text":"A go round at the end of a meeting so that people can pause and reflect on the meeting and express any issues they had or apologise for anything they want to.\n\nTekmil by the back door.","created":"20201205155414002","modified":"20201205155511270","tags":"Organising"},
{"title":"Mixlr","type":"text/x-markdown","text":"https://mixlr.com/\n\n> Broadcast live audio from one of our apps to your own website or page on Mixlr.com. Build your own audience with your live podcast, music, talk or sports show, and invite people to tune in.\n\nProprietary music streaming platform that Queer House Party were using.","created":"20210109170818312","modified":"20210109170855900","tags":"Music"},
{"title":"Modified Casio Watches","type":"text/x-markdown","text":"I've not seen this before but here's a cool mod of the Casio F91W watch.\n\n- https://n-o-d-e.net/datarunner.html\n- https://n-o-d-e.shop/","created":"20200920094526428","modified":"20200920094730915","tags":"Tech"},
{"title":"Motion sensors for home security","type":"text/x-markdown","text":"These seem like a good choice, if expensive. We'll maybe use them in both the bike sheds.\n\n- https://invidious.snopyta.org/search?q=Hosmart%20alarm%20system&page=1\n- https://www.amazon.co.uk/Rechargable-Weatherproof-Driveway-Wireless-Detector-1-base-receiver-Sensor/dp/B074WLBT89/","created":"20200716122500738","modified":"20200716122824362","tags":"Security"},
{"title":"Moto G3 iFixit Repair guide","type":"text/x-markdown","text":"https://www.ifixit.com/Device/Motorola_Moto_G_3rd_Generation","created":"20200727203428532","modified":"20200727203502651","tags":"Ecology Tech"},
{"title":"Moxie's Booklist","type":"text/x-markdown","text":"Moxie Marlinspike of Signal fame posted a reading list in a Reddit AMA. Looks good.\n\n- https://en.wikipedia.org/wiki/This_Side_of_Paradise\n-https://www.goodreads.com/book/show/403791.Letters_of_Insurgents\n- https://en.wikipedia.org/wiki/2312_(novel)\n- https://www.barnesandnoble.com/w/city-of-thieves-david-benioff/1100361922","created":"20200727201233920","modified":"20200727201502426","tags":"Books"},
{"title":"Mozilla Development Network","type":"text/x-markdown","text":"Great for learning web dev stuff.\n\n> Resources for developers, by developers.\n\nhttps://developer.mozilla.org/en-US/","created":"20200724121613346","modified":"20200724121657537","tags":"Tech"},
{"title":"Music dump December 2020","type":"text/x-markdown","text":"https://www.youtube.com/watch?v=qIIqt5UlNow\nhttps://www.youtube.com/watch?v=I9ZomwtTyfw\nv\nhttps://www.youtube.com/watch?v=Km7oAKQk0Nc\nhttps://www.youtube.com/watch?v=RkTjZR77Neo","created":"20210109172142563","modified":"20210109172240754","tags":"Music"},
{"title":"Music Theory Explorer","type":"text/x-markdown","text":"Good for learning chords and scales.\n\nhttp://music-explorer.org/\nhttps://github.com/emanchado/music-explorer","created":"20200724122304233","modified":"20200724122349295","tags":"Music"},
{"title":"New Cory Doctorow book \"Attack Surface\"","type":"text/x-markdown","text":"https://craphound.com/category/attacksurface/\n\nNew book out with accompanying lectures.","created":"20201201223655864","modified":"20201201223808318","tags":"Books"},
{"title":"New Medicinal Herb Colouring Book from Solidarity Apothercary","type":"text/x-markdown","text":"https://solidarityapothecary.org/launching-the-medicinal-herb-colouring-book/\n\n> Whatever your age and whatever your experience with herbal medicine, this book offers you a stunning collection of 50 illustrations to lose yourself in. Every illustration is accompanied by descriptions of the medicinal properties of each plant.\n>\n> From Betony to Yarrow, these plants are all around us. This book offers you a chance to expand your knowledge of common plants, whilst also providing accurate illustrations that should help you to identify the plants in the wild.","created":"20201201223249315","modified":"20201201223351771","tags":"Solarpunk Books"},
{"title":"New Tiddler","type":"text/x-markdown","text":"https://wakoma.co/\n\n> Build your own wireless mesh network that works online or offline, anywhere.\n\nOff grid mess networking project.","created":"20200920094931893","modified":"20200920095025270","tags":"P2P Solarpunk Tech"},
{"title":"NewPipe YouTube app front-end","type":"text/x-markdown","text":"https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/\n\nThe version of the excellent libre YouTube mobile app [NewPipe](https://newpipe.net) is often out of date in F-Droid and therefore broken. Here is the official repo for getting the latest version.","created":"20201223005941473","modified":"20201223010116568","tags":"Tech"},
{"title":"Nitro key","type":"text/x-markdown","text":"This looks interesting. It would be good to have access to crypto keys on the move.\n\n> Protect emails, files, hard drives, server certificates and online accounts using cryptography. Your private keys are always stored securely in the Nitrokey hardware and can't be stolen. The device is PIN-protected and is secured against brute force and hardware attacks. Backups protect against loss.\n\nhttps://www.nitrokey.com/\nhttps://www.nitrokey.com/#comparison\nhttps://shop.nitrokey.com/shop/product/nk-sta-nitrokey-start-6","created":"20201203141340959","modified":"20201223002409378","tags":"Security Tech"},
{"title":"No dig gardening","type":"text/x-markdown","text":"We've been using this method in our garden for years but I had never read the wiki page. From [Wikipedia](https://en.wikipedia.org/wiki/No-dig_gardening):\n\n## Methods\n\nNo-dig methods allow nature to carry out cultivation operations. Organic matter such as well rotted manure, compost, leaf mold, spent mushroom compost, old straw, etc., is added directly to the soil surface as a mulch at least 5-15 centimeters (26 in) deep, which is then incorporated by the actions of worms, insects and microbes. Worms and other soil life also assist in building up the soil's structure, their tunnels providing aeration and drainage, and their excretions bind together soil crumbs. \n\nThis natural biosphere maintains healthy conditions in the upper soil horizons where annual plant roots thrive. No-dig systems are said[according to whom?] to be freer of pests and disease,[citation needed] possibly due to a more balanced soil population being allowed to build up in this undisturbed environment, and by encouraging the buildup of beneficial rather than harmful soil fungi. Moisture is also retained more efficiently under mulch than on the surface of bare earth, allowing slower percolation and less leaching of nutrients.[8]\n\nAnother no-dig method is sheet mulching wherein a garden area is covered with wetted paper or cardboard, compost and topped off with landscape mulch.\n\nA no-dig system is easier than digging.[9] It is a long term process, and is reliant upon having plentiful organic matter to provide mulch material. It is also helpful to remove any perennial weed roots from the area beforehand, although their hold can be weakened by applying a light-excluding surface layer such as large sheets of cardboard or several thicknesses of spread out newspaper before adding the compost mulch. The newspaper or cardboard should be thoroughly wet to help it lie flat and keep it from blowing away until the overlying material is added. \n","created":"20200323162609845","modified":"20200324161000347","tags":"Solarpunk Ecology"},
{"title":"NODE zine","type":"text/x-markdown","text":"This looks really cool. I should add this to my library. \n\n- https://n-o-d-e.net/zine/index.html","created":"20200709133815694","modified":"20200709133844499","tags":"Tech P2P"},
{"title":"Novation Launchpad Bitwig Studio Scripts","type":"text/x-markdown","text":"This is an awesome script to use the Launchpad Pro in [Bitwig Studio](https://www.bitwig.com/en/home.html).\n\n- [https://github.com/git-moss/DrivenByMoss-Documentation/blob/master/Novation/Novation-Launchpad.md](https://github.com/git-moss/DrivenByMoss-Documentation/blob/master/Novation/Novation-Launchpad.md)","created":"20200716123008332","modified":"20200716123134742","tags":"Tech Music"},
{"title":"On opening random pdf files","type":"text/x-markdown","text":"PDF and other document formats are a security nightmare. They can have malicious scripts embedded in them and it'd be hard to detect.\n\nUnforunatly we can't escape opening random files that we download or someone sends us. That's just the reality of life these days.\n\nYou can use special operating systems such as [Tails](https://tails.boum.org/) and [Qubes OS](https://www.qubes-os.org/) but they aren't really suitable for your daily use for most people.\n\nHere are some tools that you may actually be able to use on your main computer. They both work in different ways but are pretty easy to get going with.\n\n## Firejail (Linux only)\nhttps://docs.parrotlinux.org/info/firejail/#firejail\n\n## Dangerzone\nhttps://github.com/firstlookmedia/dangerzone","created":"20200430215504860","modified":"20200430220324091","tags":"Security Tech"},
{"title":"On Productivity","type":"text/x-markdown","text":"Humans can not be “productive”. We should never measure or remark upon our own “productivity”.\n\nSystems can be productive. For example, an economic system can be productive or unproductive. A factory can be the same. A workflow can be productive. A piece software can be.\n\nWe shouldnt measure ourselves by what value we produce.\n\nEspecially when most of the value of the work we do under capitalism is extracted from us by bosses and landlords.\n\nThe lens of productivity is a inherently hierarchical way of viewing ourselves.\n\nThe obsession with productivity just pure neo-liberal economic capitalism seeping into our social relations kind of shite.\n\nWe are not systems to be “optimised”. We are people. Living, breathing, caring, loving people.\n\nFuck your productivity.","created":"20200515142109080","modified":"20200515142121851","tags":""},
{"title":"Online map for political demonstrations","type":"text/x-markdown","text":"> An Aktionskarte consists of a map extract where you can find important information like a demo route or individual points of interest. These maps should help you and your comrades to locate yourself in an unkown area. \n\n- https://www.aktionskarten.org/#/en/home","created":"20200716123210210","modified":"20200716123253662","tags":"Organising"},
{"title":"OpenWRT on BT Home Hub 5A","type":"text/x-markdown","text":"The BT Home Hub 5A is a great OpenWRT router. It's super cheap as millions were made. It's got good specs and has a modem built in that works with OpenWRT. You can get them for about £20 at the time of writing.\n\n## BT Home Hub 5A\nhttps://openwrt.org/toh/bt/homehub_v5a\nhttps://openwrt.org/docs/guide-user/network/wan/isp-configurations\n\n## EE ISP config\nhttps://ee.co.uk/help/help-new/broadband-and-landline/home-broadband/what-are-my-home-broadband-internet-settings\nhttps://community.ee.co.uk/t5/Archive/What-is-your-PPPoE/td-p/544238","created":"20200709140736676","modified":"20200709140959988","tags":"Tech"},
{"title":"Opis Retro Phones","type":"text/x-markdown","text":"- https://opis-tech.com/en/products/telephones\n- https://opis-tech.com/en/shop/60s-micro/opis-60s-micro-black\n\n60s style phones handsets including ones with 3.5 jack for smartphones and laptop.","created":"20201223002544695","modified":"20201223002652881","tags":"Tech"},
{"title":"OSSEC Host Intrusion Detection System","type":"text/x-markdown","text":"- https://www.libellux.com/ossec/#configuration-files\n- https://www.ossec.net/","created":"20201223002852468","modified":"20201223002926908","tags":"Security Tech"},
{"title":"Owncast","type":"text/x-markdown","text":"Libre Twitch style platform:\n\nhttps://github.com/owncast/owncast\nhttps://owncast.online/","created":"20210109170340741","modified":"20210109170502398","tags":"Music Video Tech"},
{"title":"PA System For a Soundsystem Co-op","type":"text/x-markdown","text":"Thinking of starting a sound system co-op. Here's some potential gear we could start with:\n\n## RCF Evox J8\nhttps://www.amazon.co.uk/RCF-Active-Speaker-Subwoofer-Package/dp/B079FYX9W7/\n\n## YAMAHA STAGEPAS 1K\nhttps://www.amazon.co.uk/YAMAHA-STAGEPAS-1K-Portable-System/dp/B07VP95V8B/ref=sr_1_4","created":"20200709132736126","modified":"20200709132915247","tags":"Organising Social"},
{"title":"Panic Button","type":"text/x-markdown","text":"I used this app as a security alarm whilst hitch-hiking. Sad to see it has become abandonware. It was really good. Except when I accidentally set if off in a club when drunk and woke my parents up at 3am.\n\n[https://github.com/PanicInitiative/PanicButton](https://github.com/PanicInitiative/PanicButton)","created":"20200607181255696","modified":"20200614201539270","tags":"Tech"},
{"title":"Patterns for a decentralised society","type":"text/x-markdown","text":"Here I will collect some resources about building a better world.\n\n## Beyond the frontlines: The building of the democratic system in North and East Syria\n \n[Beyond-the-frontlines-The-building-of-the-democratic-system-in-North-and-East-Syria-Report-Rojava-Information-Center-December-2019-V4.pdf](hyper://d4da06fac80e368ab614fb208d23fe8ddb441285f4a9cf06437f8e641a30c4a0/Beyond-the-frontlines-The-building-of-the-democratic-system-in-North-and-East-Syria-Report-Rojava-Information-Center-December-2019-V4.pdf)\n\nDistributed using [hypercore](https://beakerbrowser.com/)..\n\nPlease seed!","created":"20200331094130547","modified":"20200627155012529","status":"complete","tags":"Ecology Social Organising"},
{"title":"Paul Oakenfold Goa Mix 1994","type":"text/x-markdown","text":"[https://invidious.snopyta.org/watch?v=UFeLMFUWmWo&dark_mode=true&autoplay=1](https://invidious.snopyta.org/watch?v=UFeLMFUWmWo&dark_mode=true&autoplay=1)\n\nPaul Oakenfold Goa mix 1994 - whole 2hrs\n\n1-01: Mr. V - Give Me Life\n1-02: Grace - Skin On Skin (Orange Mix)\n1-03: Li Kwan - Point Zero\n1-04: The Disco Evangelists - De Niro (Spaceflight Mix)\n1-05: Virtual Symmetry - The V.S.\n1-06: Vangelis - Tears In Rain\n1-07: Salt Tank - Eugina (Pacific Diva)\n1-08: Hallucinogen (featuring Ben Kempton) - LSD\n1-09: Saint Etienne - Only Love Can Break Your Heart\n1-10: Wojciech Kilar - Vampire Hunters\n1-11: Electrotete - Alcatraz\n1-12: Vangelis - Bladerunner Main Titles\n1-13: Man With No Name - Floor Essence\n1-14: Scorpio Rising (3) - Dubcatcher\n1-15: Man With No Name - Evolution\n2-01: Goldie - Inner City Life\n2-02: Wojciech Kilar - Love Remembered\n2-03: Voodoo People - Co-Incidence\n2-04: The Infinity Project - Stimuli\n2-05: Trance Team - Wake Up! (Trance Mix)\n2-06: V-Tracks - Heretic Voices (Angeles Mix)\n2-07: Marmion - Schöneberg (Marmion Remix)\n2-08: Karl Biscuit - Hierophone\n2-09: Vangelis - Rachel's Song\n2-10: Virus - Sun (Oakenfold & Osborne Mix)\n2-11: Man With No Name - Deliverance\n2-12: Perfecto Allstarz - Reach Up! (Man With No Name Indian Summer Remix)\n2-13: Para-Dizer - Song Of Liberation\n2-14: Dead Can Dance - Sanvean\n2-15: 4Voice - Eternal Spirit (Northern Mix)\n2-16: Man With No Name - Sugar Rush ","created":"20200724121734426","modified":"20200724121830741","tags":"Music"},
{"title":"Permaculture Link Dump","type":"text/x-markdown","text":"Someone on Scuttlebutt shared a whole bunch of links:\n\nPermaculture Garden Toolkit: [https://ourpermaculturelife.com/permaculture-garden-toolkit/](https://ourpermaculturelife.com/permaculture-garden-toolkit/)\n\nPlant pages database: [https://pfaf.org](https://pfaf.org)\n\nPlant snap identification app: [https://www.plantsnap.com/](https://www.plantsnap.com/)\n\nHome-based living: [https://www.milkwood.net/2020/03/17/free-resources-for-home-based-living-in-the-time-of-coronavirus/](https://www.milkwood.net/2020/03/17/free-resources-for-home-based-living-in-the-time-of-coronavirus/)\n\nSkills for self-sufficiency: [https://www.pipmagazine.com.au/self-reliance/simple-skills-for-self-sufficiency/](https://www.pipmagazine.com.au/self-reliance/simple-skills-for-self-sufficiency/)","created":"20200324110223475","modified":"20200324110400942","tags":""},
{"title":"Photographing Wars in the Middle East","type":"text/x-markdown","text":"https://video.vice.com/en_uk/video/vice-photographing-wars-in-the-middle-east/5f526c63c92bac70345e8861\n\n> Former soldier turned photographer, Alison Baskerville, talks about gender, conflict and the impact war can have on the men and women serving on the battlefield. Exploring gender equality, military occupation and female identity in the forces, plus the long-term consequences of armed conflict, she recalls her experiences photographing wars in the Middle East.","created":"20200920101101921","modified":"20200920101144358","tags":"Lists"},
{"title":"Pinephone","type":"text/x-markdown","text":"The Pinephone is a really cool piece of mobile computing hardware designed to run proper Linux. All the basic phone stuff seems to be supported. Could be a great secondary device to get away from it all. Unfortunately it's very rarely in stock. Might be easier to get one second hand.\n\n- https://www.pine64.org/pinephone/\n- https://store.pine64.org/product/pinephone-community-edition-ubports-limited-edition-linux-smartphone/\n- https://wiki.mobian-project.org/doku.php?id=start\n- https://wiki.mobian-project.org/doku.php?id=apps","created":"20200709132935280","modified":"20200709133229442","tags":"Tech"},
{"title":"Possessor review Brandon Cronenberg's terrifying sci-fi horror freak-out","type":"text/x-markdown","text":"https://www.theguardian.com/film/2020/nov/26/possessor-review-brandon-cronenberg-andrea-riseborough-sc0fi-horror\n\n> The directors thrillingly ingenious tale of mind-invasion technology, starring Andrea Riseborough, barrels towards the most outrageous final twist imaginable","created":"20201201232456282","modified":"20201201232528043","tags":"Films"},
{"title":"Privacy respecting DNS service","type":"text/x-markdown","text":"Most censorship on the UK is done on the level of the [Domain Name System (DNS)](https://en.wikipedia.org/wiki/Domain_Name_System). In general, DNS is not a very secure system and does have good mechanisms to prevent that kind of [ISP](https://en.wikipedia.org/wiki/Internet_service_provider) censorship.\n\nIn order to circumvent that censorship you can use a privacy respecting DNS provider. I have been using [LibreDNS](https://libredns.gr/) from the [LibreOps](https://libreops.cc/) collective.\n\nIt's very easy to use DNS and HTTPS and over TLS in the instructions on their site. You can also block ads. \n\nIt's worth checking it out:\nhttps://libredns.gr/\n\nYou can also of cource us [Tor Browser](https://www.torproject.org/) which I reccomend or perhaps a VPN.","created":"20200425133559838","modified":"20200425134213356","tags":"Tech"},
{"title":"Push to Talk: Online mini Chaos Congress","type":"text/x-markdown","text":"I will hopefully be able to attend this online event.\n\n> During the past couple of months, we have increasingly moved our lives into cyberspace, where chaos is digitally distributed.\n> \n> We have gone on-line for events, streamed content and clicked on talk recordings. There was lots of lecturing — now we are looking for more interaction: Instead of just watching a stream, lets go do cool stuff together!\n> \n> From September 4-6 we will have the third digitally distributed online chaos, this time under the theme “Push to talk”. \n\n- https://di.c3voc.de/ptt:start\n- https://di.c3voc.de/ptt:en:start","created":"20200817130052142","modified":"20200817130221803","tags":"Security Organising Tech"},
{"title":"Queer Solarpunk Blog Post","type":"text/x-markdown","text":"My friend wrote a nice blog post about queer solarpunk futures.\n\nhttps://solarpunkdruid.com/2020/08/09/queer-solarpunk/","created":"20200817124710814","modified":"20200817124758231","tags":"Social"},
{"title":"Qwant Open Street Maps frontend","type":"text/x-markdown","text":"https://www.qwant.com/maps/","created":"20200724122402638","modified":"20200724122423293","tags":"Tech"},
{"title":"Raspberry Pi as home network monitor","type":"text/x-markdown","text":"We have a lot of Wifi issues in my house but also seemingly upstream issues. Here are some tools I am considering to better monitor those:\n\n- http://www.greatwhitewifi.com/2016/02/12/network-monitoring-with-raspberry-pi-part-2-smokeping/\n- https://community.spiceworks.com/how_to/96949-raspberrypi-rpi-smokeping-setup-and-configuration\n- https://oss.oetiker.ch/smokeping/doc/smokeping.en.html\n- https://pimylifeup.com/raspberry-pi-internet-speed-monitor/\n","created":"20200425133021736","modified":"20200425133205434","tags":"Tech"},
{"title":"Recipes","type":"text/x-markdown","text":"### Banana Peel \"Bacon\"\nhttps://rhiaro.co.uk/2020/04/photos-bananacon#","created":"20200421103740738","modified":"20200421103832345","tags":"Food"},
{"title":"Relationship Anarchy","type":"text/x-markdown","text":"> Relationship anarchy (sometimes abbreviated RA) is the application of anarchist principles to intimate relationships. Some especially important values include autonomy, anti-hierarchical practices, lack of state control, anti-normativity, and community interdependence. \n>\n> RA can be considered a type of non-monogamy, but moreso is explicitly anti-monogamy. This anti-monogamy is distinct from polyamory, solo poly, and other forms of “dating” due to their reproduction of many of the same oppressive structures found within monogamy (amatonormativity, pedestalization of sex, reinforcement of hierarchies of intimacy, autonomy-limiting rules, etc.).\n> \n- https://en.wikipedia.org/wiki/Relationship_anarchy\n- https://en.wikipedia.org/wiki/Anarchism_and_issues_related_to_love_and_sex\n- https://en.wikipedia.org/wiki/Individualist_anarchism_in_Europe\n- https://theanarchistlibrary.org/library/andie-nordgren-the-short-instructional-manifesto-for-relationship-anarchy\n- https://theanarchistlibrary.org/library/crimethinc-love-anarchy-and-drama\n- https://greatist.com/connect/relationship-anarchy#infographic\n- https://polyamorousliving.com/2019/05/10/redefining-relationships-through-anarchy/\n- ","created":"20200502103857468","modified":"20201223004035503","tags":"Care Social"},
{"title":"Remove Unused Flatpak Runtimes","type":"text/x-markdown","text":"```\nflatpak uninstall --unused\n```","created":"20201205144509732","modified":"20201205144535957","tags":"Tech"},
{"title":"Reverb pre delay calculator","type":"text/x-markdown","text":"> A tool to calculate syncopated reverb pre-delay & decay (RT60) times. \n\nhttps://studioslave.com/reverbcalculator/","created":"20201201225325896","modified":"20201201225403507","tags":""},
{"title":"RSS feed for Mastodon and Pixelfed accounts","type":"text/x-markdown","text":"[RSS feeds](https://en.wikipedia.org/wiki/RSS) are super useful for a variety of things. Software that is part of the [Fediverse](https://en.wikipedia.org/wiki/Fediverse) creates a RSS feed of its users public posts. You just need the slightly obscure URL which is different for different Fediverse platforms. I wish they made visible buttons for this as its a really underrated feature.\n\n## Mastodon\nhttps://sunbeam.city/@kawaiipunk.rss\n\n## Pixelfed\nhttps://pixelfed.social/users/kawaiipunk.atom","created":"20200630235033309","modified":"20200630235955905","tags":"Social Tech"},
{"title":"Rural Co-ops","type":"text/x-markdown","text":"From a conversation with a friend.\n\n- https://en.wikipedia.org/wiki/Longo_Ma%C3%AF\n- https://www.resilience.org/stories/2015-02-03/forty-years-of-longo-mai/\n- https://archive.org/details/NomadicEcoVillages/mode/2up\n- http://thebookshelf.org.uk/\n- https://hub.libranet.de/page/foodcommons/home\n- https://app.solidbase.info/","created":"20200707211442420","modified":"20200707211709198","tags":"Ecology Solarpunk Organising"},
{"title":"Sad Cookbook - Simple recipes for sad times","type":"text/x-markdown","text":"Some friends made a website to collect easy recipes for those suffering from mental health or executive dysfunction issues. Would love to add some more vegan ones.\n\nhttps://sadcookbook.recipes/sad/","created":"20200817125929286","modified":"20200817130029861","tags":"Care Food"},
{"title":"Sarah Brightman - I Lost My Heart to a Starship Trooper","type":"text/x-markdown","text":"Cool disco stomper with a silly gay Star Trek video.\n\nhttps://www.youtube.com/watch?v=1kTgofG1Q-Q","created":"20210109170506399","modified":"20210109170608156","tags":"Video Music"},
{"title":"Scuttlebot written in C","type":"text/x-markdown","text":"sbotc\n\nA command-line SSB client in C. Use like the sbot command (except for server/start).\n\nhttps://git.scuttlebot.io/%25133ulDgs%2FoC1DXjoK04vDFy6DgVBB%2FZok15YJmuhD5Q%3D.sha256","created":"20200724122433264","modified":"20200724122519248","tags":"Tech P2P"},
{"title":"Seat 61","type":"text/x-markdown","text":"This is a cool website someone recommended at Congress for travelling by train.\n\nhttps://www.seat61.com/\nhttps://www.seat61.com/aboutme.htm","created":"20210109170614688","modified":"20210109170734888","tags":"Travel"},
{"title":"Security for the savvy leftist, Part 1: OpSec","type":"text/x-markdown","text":"I saw a friend on Mastodon post this:\n\nhttps://wxcafe.net/posts/security_for_the_savvy_leftist_part_%E2%85%A0_opsec/","created":"20200704195216777","modified":"20200705152427079","tags":"Tech Security Organising"},
{"title":"Security Monitoring Software","type":"text/x-markdown","text":"- https://www.shodan.io/\n- https://developer.shodan.io/pricing\n- https://cisofy.com/demo/\\\n- https://alternativeto.net/software/shodan/\n- https://alternativeto.net/software/zoomeye/about/\n- https://doc.ivre.rocks/en/latest/usage/use-cases.html#your-own-shodan-zoomeye-censys-binaryedgeio-whatever\n- https://censys.io/","created":"20210109173113352","modified":"20210109173214752","tags":"Security Tech"},
{"title":"seedvault - encrypted Android backups","type":"text/x-markdown","text":"> Features\n> Backup application data to a flash drive.\n Restore application data from a flash drive.\n User-friendly encryption using a mnemonic phrase (BIP39).\n Automatic daily backups that run in the background.\n\nThis is the best Android backup system I've seen. It doesn't require root but must be pre-installed via the OS.\n\nhttps://github.com/seedvault-app/seedvault\nhttps://github.com/tlambertz/seedvault_backup_parser","created":"20201211135729688","modified":"20201211140002955","tags":"Tech Mobile"},
{"title":"Setting snap package auto upgrade frequency","type":"text/x-markdown","text":"[Snap packages](https://snapcraft.io/docs) are a packaging format for Linux. It's installed by default on Ubuntu.\n\nSnap packages update automatically which can be super annoying when you're trying to get work done.\n\nThere is a way to stop them auto updating all together but for me, I just want them to auto update outside of work hours.\n\nHere are the docs for that:\nhttps://snapcraft.io/docs/keeping-snaps-up-to-date\n\nI ran:\n```\nsudo snap set system refresh.timer=mon-sun,19:00 \n```\n\nNow they only auo update each day at 19:00.","created":"20210414123703189","modified":"20210414124048590","tags":"Tech"},
{"title":"Sgian-dubh (Dirk) knife","type":"text/x-markdown","text":"https://en.wikipedia.org/wiki/Sgian-dubh\n\n> The sgian-dubh (/ˌskiːən ˈduː/ skee-ən-DOO; Scottish Gaelic pronunciation: [s̪kʲənˈt̪u]) is a small, single-edged knife (Scottish Gaelic: sgian) worn as part of traditional Scottish Highland dress along with the kilt. Originally used for eating and preparing fruit, meat, and cutting bread and cheese, as well as serving for other more general day-to-day uses such as cutting material and protection, it is now worn as part of traditional Scottish dress tucked into the top of the kilt hose with only the upper portion of the hilt visible. The sgian-dubh is normally worn on the same side as the dominant hand. ","created":"20210109172342692","modified":"20210109172504696","tags":"History"},
{"title":"Shoes","type":"text/x-markdown","text":"I need some new shoes as my current trainers are falling apart. I went down a total rabbit hole. Here was the result.\n\n* [Kickers Lennon Boatshoe Shoes | Shop Kickers Online](https://www.kickers.co.uk/kick-hi-c9/lennon-boatshoe-p6577 \"Kickers Lennon Boatshoe Shoes | Shop Kickers Online\")\n* [Kickers Lennon Boatshoe Shoes | Shop Kickers Online](https://www.kickers.co.uk/kick-hi-c9/lennon-boatshoe-p6578 \"Kickers Lennon Boatshoe Shoes | Shop Kickers Online\")\n* [2 - 3 |](https://www.size.co.uk/size/9/?from=24&maxprice-gbp=60.01&minprice-gbp=15 \"2 - 3 |\")\n* [Black Reebok Classic Nylon | size?](https://www.size.co.uk/product/black-reebok-classic-nylon/15969718/ \"Black Reebok Classic Nylon | size?\")\n* [Multi Puma RS-2K RF | size?](https://www.size.co.uk/product/multi-puma-rs-2k-rf/16033757/ \"Multi Puma RS-2K RF | size?\")\n* [12 - 18 | Mens - Footwear | size?](https://www.size.co.uk/mens/footwear/size/9/latest/?from=264 \"12 - 18 | Mens - Footwear | size?\")\n* [adidas Samba Vegan Shoes - White | adidas UK](https://www.adidas.co.uk/samba-vegan-shoes/H01878.html?forceSelSize=9 \"adidas Samba Vegan Shoes - White | adidas UK\")\n* [9 | Men's | Footwear | Multisport & Walking Shoes](https://www.gooutdoors.co.uk/mens/footwear/multisport-trail/si:9/ \"9 | Men's | Footwear | Multisport & Walking Shoes\")\n* [Merrell YOKOTA SPORT LOW GTX | GO Outdoors](https://www.gooutdoors.co.uk/15909649/merrell-yokota-sport-low-gtx-15909649 \"Merrell YOKOTA SPORT LOW GTX | GO Outdoors\")\n* [Merrell Moab 2 Ventilator Shoes | GO Outdoors](https://www.gooutdoors.co.uk/15897813/merrell-moab-2-ventilator-shoes-15897813 \"Merrell Moab 2 Ventilator Shoes | GO Outdoors\")\n* [Behind The Shoe | Merrell Moab 2 - YouTube](https://www.youtube.com/watch?v=6Ybctxy8SwM&feature=emb_logo \"Behind The Shoe | Merrell Moab 2 - YouTube\")\n* [Multi Activity Shoes - Meindl UK](https://www.meindl.co.uk/products/mens/multi-activity-shoes/ \"Multi Activity Shoes - Meindl UK\")\n* [Salewa Men's Ms Wildfire Gore-tex Trekking & Hiking Boots: Amazon.co.uk: Shoes & Bags](https://www.amazon.co.uk/Salewa-Wildfire-Hiking-Shoes-Orange/dp/B07M8KSC54/ref=cm_cr_arp_d_product_top?ie=UTF8&th=1&psc=1 \"Salewa Men's Ms Wildfire Gore-tex Trekking & Hiking Boots: Amazon.co.uk: Shoes & Bags\")\n* [SALOMON Men's Speedcross 4 GTX Trail Running Shoes: Amazon.co.uk: Shoes & Bags](https://www.amazon.co.uk/Salomon-Speedcross-Footwear-Waterproof-Metallic/dp/B017SR0BB0/ref=bmx_4?pd_rd_w=ODRXb&pf_rd_p=42ba6dbf-f620-4798-989e-01ad030ff706&pf_rd_r=6SRB9RKM8MZC23Y4G66G&pd_rd_r=c7c37e76-521c-4da0-921e-8e7d263486d2&pd_rd_wg=EshCC&pd_rd_i=B017SR0BB0&th=1&psc=1 \"SALOMON Men's Speedcross 4 GTX Trail Running Shoes: Amazon.co.uk: Shoes & Bags\")\n* [Salewa Mens Wildfire GORE-TEX® Approach Shoes | GO Outdoors](https://www.gooutdoors.co.uk/15983554/salewa-mens-wildfire-gore-tex-approach-shoes-15983554 \"Salewa Mens Wildfire GORE-TEX® Approach Shoes | GO Outdoors\")\n* [Mountain Shoes & Boots · Men's Outdoor Footwear | Salewa® UK](https://www.salewa.com/en-gb/men-mountain-footwear?p=1&o=3&n=36&f=113 \"Mountain Shoes & Boots · Men's Outdoor Footwear | Salewa® UK\")\n* [Wildfire GORE-TEX® Men's Shoes | Salewa® UK](https://www.salewa.com/en-gb/wildfire-gore-tex-mens-shoes-00-0000063487?number=00-0000063487_0000000079 \"Wildfire GORE-TEX® Men's Shoes | Salewa® UK\")\n* [Men's Walking Shoes | Order From The Experts | Cotswold Outdoor](https://www.cotswoldoutdoor.com/c/outdoor-footwear/mens-outdoor-shoes/mens-walking-shoes.html?page=0&size=48&filter=%2526filter%253Duk_size_description%253A%2528sz45c48cce%2529 \"Men's Walking Shoes | Order From The Experts | Cotswold Outdoor\")\n* [Gear Review: Salewa Wildfire Hiking-Approach Shoes | The Big Outside](https://thebigoutside.com/gear-review-salewa-wildfire-hiking-approach-shoes/ \"Gear Review: Salewa Wildfire Hiking-Approach Shoes | The Big Outside\")\n* [Waterproof Socks | Rana Socks for Hiking and Biking | Alpkit](https://alpkit.com/products/rana-waterproof-socks \"Waterproof Socks | Rana S
{"title":"Signal Voice Call Echo Problems","type":"text/x-markdown","text":"Apparently some devices have issues with echo cancellation which is why you get problems in Signal calls sometimes.\n\nhttps://github.com/signalapp/Signal-Android/blob/master/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java#L301","created":"20200727190505824","modified":"20200727190600346","tags":"Tech"},
{"title":"Siren Moon Illustrations","type":"text/x-markdown","text":"https://ko-fi.com/sirenmoonillustrations/shop","created":"20201201232332766","modified":"20201201232413079","tags":"Solarpunk Art"},
{"title":"Skills for Revolutionary Survival: 1. Trauma Medical Gear","type":"text/x-markdown","text":"There's plenty of links in this that I need to look into:\n\nhttps://iaf-fai.org/2020/08/31/skills-for-revolutionary-survival-1-trauma-medical-gear/","created":"20200920100937862","modified":"20200920101031961","tags":"Care Organising"},
{"title":"Slax - Live USB distro","type":"text/x-markdown","text":"https://www.slax.org/customize.php\nhttps://www.slax.org/","created":"20201223005046598","modified":"20201223005111447","tags":"Tech"},
{"title":"Slow news in a fast world","type":"text/x-markdown","text":"If you really want to avoid the news sludge and just get some stats and headlines on the pandemic each day in your terminal, you might want to use this service:\n\n[https://github.com/sagarkarira/coronavirus-tracker-cli](https://github.com/sagarkarira/coronavirus-tracker-cli)\n\nIt just seems to cut out all the bullshit for me when you're just getting the info in a text only format.\n\n## New updates\n`curl https://corona-stats.online/updates`\n\n## Pre country stats\n`curl https://corona-stats.online/UK`\n\n## Realtime worldwide stats\n`curl https://corona-stats.online?source=2`","created":"20200321230617757","modified":"20200321230950356","tags":"Tech"},
{"title":"Solarpower","type":"text/x-markdown","text":"A place to compile knowledge about solarpower, solar panels, batteries etc. \n\n## Learning tools\n- https://www.bimblesolar.com/beginnersguide\n- https://www.bimblesolar.com/solarcalc\n\n## Small solar systems\n- https://voltaicsystems.com/arc20w-kit/\n- https://www.bimblesolar.com/solar/individual/usb-solar-6w-sunpower\n\n","created":"20200507111110923","modified":"20200507111346266","tags":""},
{"title":"Solarpunk: To walkaway or to stay and fight?","type":"text/x-markdown","text":"## Tensions\nOne of the main tenants of the solarpunk movement has tended to be based around the idea of \"walkaway\" or to removes one's self from society in order to accelerate the process of learning and self-education and start learning how to have more autonomy from capitalism. \n\nHowever temporary this escape proves to be, there is no doubt this strategy is at odds with the organising focused parts of the left. The organising focused left requires someone to place themselves as close to the antagonisms of class under capitalism, e.g. the workplace, privately rented housing, the site of ecological destruction, within a political party and so forth.\n\nWalkaway points to a divergence from this strategy in the sense that it accepts the toll that these conditions has on a person's intellectual and technical development and that for many people in highly complex capitalist economies, alienation is at a level where people cannot conceive a better world. \n\nWe are totally disconnected from a flourishing political and philosophical life and from any sort of autonomy and freedom. Vast economic pressures are piled upon us, remote and out of reach. Our consciousness is reduced to mundane, exhausting and relentless struggle for survival.\n\nWithout creating space for us to experiment, play, explore, it's incredibly difficult to imagine a better life for ourselves. One of the strengths of Solarpunk is that it makes space for positive visions of the future. However flawed these experiments are, they have the potential for inspiring a whole new group of people that a purely pragmatic organising project might not.\n\nThe concept of walking away presents many problems that I would like to see critiqued. If some of us are to walkaway (whatever that looks like), what happens to the others that are left behind. Are we to abandon our friends and family to the ravages of neo-liberal capitalism? Are we to abandon the anti-imperialist struggle to restrain our nation states from engaged in out and out war? Are we to abandon our unions and social organisations?\n\nI don't really buy the idea that walkaway is simply bourgeois escapism. There are already many communities that live in a way that resembles the walkaway ethos. We've been here many times before. Sometimes communities are forced into the walkaway life due to racism and poverty. There are also many that simply using their small fortunes made from programming for big tech companies, in order to live a more autonomous life. I fear reconciling these extremes may prove very difficult unless the solarpunk movement incorporates class based analysis.\n\nI would purpose that unless those that walkaway are able to pass on the knowledge and technical skills back through flows of value to the \"default\" society, then their efforts are wasted to the cause individualistic self improvement and woo arts and crafts. In Cory Doctorow's book Walkaway, this tension is quite extensively discussed but not satisfactorily concluded. I would like to see more explorations of these possibilities.\n\n## Questions\n- Why do you want to walkway?\n- What does it mean to walkaway?\n- Is it useful to walkaway?\n- What happens to the people who are left behind?\n\n## Possible references\n- Value flows from urban to rural - %25T935LJzh6RehG3mHLNbbu3icSo08XVg7SPLym2W5BSU%3D.sha256\n- Walkaway by Cory Doctorow\n- Back to the land movement\n- UK rave and travellers movement\n- Capitalist Realism by Mark Fisher\n- Cooperation Jackson - https://invidiou.sh/watch?v=_Nt9Z2P7mPY\n","created":"20200311233839552","modified":"20200312004016610","tags":"Social Solarpunk"},
{"title":"SSB-Room","type":"text/x-markdown","text":"I recently on-boarded someone onto Scuttlebutt using a friends hosted ssb-room server. \n\nIt went super well. I should probably run one myself\n\n- https://github.com/staltz/ssb-room\n- https://github.com/staltz/ssb-room/blob/master/manual-setup.md\n\n\n","created":"20200716130049238","modified":"20200716130225277","tags":"Solarpunk Tech"},
{"title":"Starship: cross shell prompt written in rust","type":"text/x-markdown","text":"https://starship.rs/\n\n> The minimal, blazing-fast, and infinitely customizable prompt for any shell! ","created":"20201201225512776","modified":"20201201225613672","tags":"Tech"},
{"title":"Stopping phishing campaigns with bash","type":"text/x-markdown","text":"Really cool response to a targeted phishing attack using basic tools. \n\nhttps://blog.haschek.at/2020/stopping-phishing-campaigns-with-bash.html","created":"20200817123252364","modified":"20200817123340727","tags":"Tech"},
{"title":"Storyville: Pepe The Frog","type":"text/x-markdown","text":"https://www.bbc.co.uk/iplayer/episode/m000nwrq/storyville-pepe-the-frog-feels-good-man\n\n> Pepe the Frog started life in 2005 as a cute cartoon character in Boys Club, an American indie comic on Myspace. Today, he is known as an international hate symbol after being hijacked by the alt-right. Pepe the Frog: Feels Good Man follows Pepes creator, artist Matt Furie, as he fights to bring back his lovable comic-book character from the dark forces who stole him. \n>\n> As the internet exploded, memes of the benign and chill frog-dude started sweeping the internet with lightning speed. Once his image found its way into controversial online community 4chan the anonymous, anything-goes forum rife with misogyny and racism - there was no turning back. Pepe re-emerged from the darkest corner of the internet decorated with swastikas and spewing racist slurs. He was even caught up in Donald Trumps presidential campaign. \n>\n> Exactly how that happened is a wild journey into the heart of online life today and an exploration of how a character meant to bring joy and fun slowly morphed into something else. Maybe, just maybe, he can change again","created":"20201201223833350","modified":"20201201223935387","tags":"Video Documentary"},
{"title":"Sunbeam.City in danger","type":"text/x-markdown","text":"On 6th March 2020, Sunbeam.city was in danger of shutting down due to a incident of which the details are not clear to me yet.\n\nCan anyone please help me mirror the SunbeamCity wiki? Unfortunately I dont have a copy of the cafe.sunbeam.city blog. It went down a while ago. I didn't think it neccesary to archive the Loomio.\n\n## P2P/Dat\nI put it on dat. You just need Beaker Browser.\n\nJust go to this dat address and toggle and click “Seed this sites files”.\n\n[dat://cf9de5d87118ad22ecd927df1c1b174632c6a1920ade2ef57f75e8421017ccc5/doku.htm](dat://cf9de5d87118ad22ecd927df1c1b174632c6a1920ade2ef57f75e8421017ccc5/doku.html)\n\n## Wayback Machine\n[https://web.archive.org/web/20200306182019/https://wiki.sunbeam.city/doku.php](https://web.archive.org/web/20200306182019/https://wiki.sunbeam.city/doku.php)","created":"20200306190458038","modified":"20200312004920770","revision":"","tags":"Journal"},
{"title":"Tech","text":"","color":"#efeaff","created":"20200321185137582","modified":"20200321232558130"},
{"title":"Tekmîl: Creating a Culture of Constructive Criticism","type":"text/x-markdown","text":"Tekmîl is a social system of criticism that emerged out of the Kurdish freedom movement. I think it could be really effective in social movements around the world.\n\n> Tekmîl roughly translates to “report”. On its face it sounds fairly mundane, however a more conceptual definition would be that of revolutionary constructive criticism. Tekmîl typically follow up everything such as military operations, training sessions, civil projects, or simple daily tasks. These sessions can be called at any time by anyone in either the civil or military structures in Rojava.\n>\n> The structure of Tekmîl is based on giving and receiving critiques and self-critiques. The process is based on the foundations of Hevaltî. Hevaltî roughly translates to friendship or comradeship. It is the idea that we work together, we help each other, we share everything from the tangible to the intangible not because we expect something in return but simply because we are comrades, that we are humans living, struggling and experiencing life together, that we are sharing the same purpose of trying to advance the collective wellbeing. It is the idea that we can trust and believe in each other and that we need not fear ulterior intention.\n\n- https://komun-academy.com/2020/03/27/struggling-against-the-system-in-ourselves-criticism-and-self-criticism/\n\n- https://komun-academy.com/2018/08/11/tekmil-creating-a-culture-of-constructive-criticism/\n\n- https://aatqaarham.wordpress.com/2020/06/13/tekmil/\n\n- https://pndk.org/en/node/222\n\n- https://kurdishsolidaritynetwork.wordpress.com/2020/07/14/lessons-from-rojava-seminar-4-podcast/","created":"20200814132558935","modified":"20200814132923586","tags":"Social Organising"},
{"title":"The Commoner","type":"text/x-markdown","text":"https://www.thecommoner.org.uk/\nhttps://www.thecommoner.org.uk/about/\n\n> The Commoner is an independent, anarchist publication written by commoners and for commoners. It is a springboard for common voices, ideas, and hopes. Our editors, writers and supporters want to see the dawn of a common world, where every individual, anywhere, may enjoy autonomy, peace and security.","created":"20210109171239571","modified":"20210109171316748","tags":"Organising Reading"},
{"title":"The Dinghy Cruising Companion: Tales and Advice from Sailing a Small Open Boat","type":"text/x-markdown","text":"It'd be good to find a non Amazon place to buy this book:\n\nhttps://www.amazon.co.uk/Dinghy-Cruising-Companion-Roger-Barnes/dp/1408179164","created":"20201211140219559","modified":"20201211140254945","tags":"Solarpunk"},
{"title":"The Last Clarion House","type":"text/x-markdown","text":"https://youtu.be/xsQznVb3biM\n\nCool documentary about a 100 year old socialist social centre in the north of England.\n\n> Documentary about the Last Clarion House, Pendle, Lancashire.\nDOP Nick Gordon-Smith\nEditor Cliff West\nMusic by Vini Reilly, Durutti Column\nDirector Charlotte Bill\nClapham Film Unit and Clarion House\nFunded by the Heritage Lottery Fund","created":"20201201224203824","modified":"20201201224322032","tags":"Video Documentary"},
{"title":"The Megalithic Portal","type":"text/x-markdown","text":"I found a call site that has a map and wiki about all of the ancient sites around the world. \n\nhttps://www.megalithic.co.uk/index.php\nhttps://www.megalithic.co.uk/le_megalith_map.html#12/52.4605/-2.1468\nhttps://www.megalithic.co.uk/article.php?sid=31243","created":"20200702111803727","modified":"20200702111931124","tags":"Ecology"},
{"title":"The Racial Bias Built Into Photography","type":"text/x-markdown","text":"https://www.nytimes.com/2019/04/25/lens/sarah-lewis-racial-bias-photography.html\n\n> Sarah Lewis explores the relationship between racism and the camera. ","created":"20210109170747750","modified":"20210109170809549","tags":"Psychology Art"},
{"title":"The Reasonable Person's Guide To Prepping","type":"text/x-markdown","text":"I listened to the episode of the Worst Year Ever podcast with Robert Evans where they talk about prepping. In the show notes, there was a list of other resources so I'm just copying that here.\n\n## Resources:\n### Emergency Preparedness Checklist:\n\nhttps://theprepared.com/prepping-basics/guides/emergency-preparedness-checklist-prepping-beginners/\n\n### Emergency Medicine Podcast:\n\nhttp://embasic.org/podcast-direct-download/\n\n### The Survival Doctor's Guide to Wounds:\n\nhttps://www.amazon.com/Survival-Doctors-Guide-Wounds-Doctor-ebook/dp/B008M2E4IM/ref=sr_1_1?keywords=the+survival+doctor%27s+guide+to+wounds&qid=1584490006&s=books&sr=1-1\n\nhttps://www.scribd.com/book/194101508/The-Survival-Doctor-s-Guide-to-Wounds\n\n### Bushcraft 101:\n\nhttps://www.amazon.com/dp/B00MIMHPII/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1\n\n### Street Medic Guide:\n\nhttps://www.paperrevolution.org/street-medic-guide/\n\n### Military Medical:\n\nhttps://fas.org/irp/doddir/milmed/soldiers.pdf\n\n### Rifles For Rookies:\n\nhttps://socialistra.org/edu/assets/Rifles-For-Rookies.pdf\n\n### Urban Foraging Guide:\n\nhttps://fallingfruit.org/docs/David%20Craft%20-%20Urban%20Foraging.pdf\n\n### A Preppers Guide to Pickling:\n\nhttps://storageprepper.com/food/preppers-guide-pickling/\n\n### Freezing Vegetables:\n\n https://nchfp.uga.edu/publications/uga/uga_freeze_veg.pdf\n\n### Dried Beans Conversions and Measurements:\n\nhttps://www.thespruceeats.com/dried-bean-conversions-and-measurements-1388322\n\n### The End:\n\nhttps://theend.substack.com/p/welcome-to-the-end","created":"20200919193605363","modified":"20200919193856595","tags":"Lists Organising"},
{"title":"The Scuttlebutt Song","type":"text/vnd.tiddlywiki","text":"! Lyrics\n\n```\nGonna scuttle with my friends\nWe're gonna sail the cyber seas\nTime to go off-grid\nAnd build communities \n\nBorders they'll fade\nThe tyrants they'll fall\nWe're gonna to build a new world\nSolarpunk for all\n\nI've got my crypto keys\nAnd you've got yours\nWe're connecting peer to peer\nLike dark crystals in the void\n\nAll things in common\nOne big pirate's shoal\nWe're going to build a new world\nScuttlebutt for all\n```\n\ncc-noncommerical-sharealike licensed\n","created":"20200311232130224","modified":"20200311232457327","tags":"P2P Music"},
{"title":"TiddlyWiki Markdown Plugin","type":"text/vnd.tiddlywiki","text":"I installed this and it's working great!\n\nhttps://tiddlywiki.com/plugins/tiddlywiki/markdown","bag":"default","created":"20200227000040083","modified":"20200307223139114","revision":"0","tags":"Tech"},
{"title":"TiddlyWiki Readme","type":"text/vnd.tiddlywiki","text":"\u003Cp>Welcome to \u003Ca class=\"tc-tiddlylink tc-tiddlylink-resolves\" href=\"https://tiddlywiki.com/static/TiddlyWiki.html\">TiddlyWiki\u003C/a>, a non-linear personal web notebook that anyone can use and keep forever, independently of any corporation.\u003C/p>\u003Cp>\u003Ca class=\"tc-tiddlylink tc-tiddlylink-resolves\" href=\"https://tiddlywiki.com/static/TiddlyWiki.html\">TiddlyWiki\u003C/a> is a complete interactive wiki in \u003Ca class=\"tc-tiddlylink tc-tiddlylink-resolves\" href=\"https://tiddlywiki.com/static/JavaScript.html\">JavaScript\u003C/a>. It can be used as a single HTML file in the browser or as a powerful Node.js application. It is highly customisable: the entire user interface is itself implemented in hackable \u003Ca class=\"tc-tiddlylink tc-tiddlylink-resolves\" href=\"https://tiddlywiki.com/static/WikiText.html\">WikiText\u003C/a>.\u003C/p>\u003Cp>Learn more and see it in action at \u003Ca class=\"tc-tiddlylink-external\" href=\"https://tiddlywiki.com/\" rel=\"noopener noreferrer\" target=\"_blank\">https://tiddlywiki.com/\u003C/a>\u003C/p>\u003Cp>Developer documentation is in progress at \u003Ca class=\"tc-tiddlylink-external\" href=\"https://tiddlywiki.com/dev/\" rel=\"noopener noreferrer\" target=\"_blank\">https://tiddlywiki.com/dev/\u003C/a>\u003C/p>\u003Ch1 class=\"\">Join the Community\u003C/h1>\u003Cp>\n\u003Ch2 class=\"\">Users\u003C/h2>\u003Cp>The TiddlyWiki discussion groups are mailing lists for talking about TiddlyWiki: requests for help, announcements of new releases and plugins, debating new features, or just sharing experiences. You can participate via the associated website, or subscribe via email.\u003C/p>\u003Cul>\u003Cli>The main TiddlyWiki group: \u003Ca class=\"tc-tiddlylink-external\" href=\"http://groups.google.com/group/TiddlyWiki\" rel=\"noopener noreferrer\" target=\"_blank\">http://groups.google.com/group/TiddlyWiki\u003C/a>\u003Cblockquote>\u003Cp>Note that you do not need a Google Account to join the discussion groups. Subscribe by sending an email to \u003Ca class=\"tc-tiddlylink-external\" href=\"mailto:tiddlywiki+subscribe@googlegroups.com\" rel=\"noopener noreferrer\" target=\"_blank\">mailto:tiddlywiki+subscribe@googlegroups.com\u003C/a> or \u003Ca class=\"tc-tiddlylink-external\" href=\"mailto:tiddlywikidev+subscribe@googlegroups.com\" rel=\"noopener noreferrer\" target=\"_blank\">mailto:tiddlywikidev+subscribe@googlegroups.com\u003C/a>.\u003C/p>\u003C/blockquote>\u003Cul>\u003Cli>An enhanced group search facility is available on \u003Ca class=\"tc-tiddlylink-external\" href=\"https://www.mail-archive.com/tiddlywiki@googlegroups.com/\" rel=\"noopener noreferrer\" target=\"_blank\">mail-archive.com\u003C/a>\u003C/li>\u003C/ul>\u003C/li>\u003Cli>Watch recordings of our regular \u003Ca class=\"tc-tiddlylink tc-tiddlylink-resolves\" href=\"https://tiddlywiki.com/static/TiddlyWiki%2520Hangouts.html\">TiddlyWiki Hangouts\u003C/a>\u003C/li>\u003Cli>Follow \u003Ca class=\"tc-tiddlylink-external\" href=\"http://twitter.com/TiddlyWiki\" rel=\"noopener noreferrer\" target=\"_blank\">@TiddlyWiki on Twitter\u003C/a> for the latest news\u003C/li>\u003Cli>\u003Cstrong>New: Join us on our live chat at \u003Ca class=\"tc-tiddlylink-external\" href=\"https://gitter.im/TiddlyWiki/public\" rel=\"noopener noreferrer\" target=\"_blank\">https://gitter.im/TiddlyWiki/public\u003C/a> !\u003C/strong>\u003C/li>\u003C/ul>\u003Ch2 class=\"\">Developers\u003C/h2>\u003Cul>\u003Cli>The \u003Ca class=\"tc-tiddlylink tc-tiddlylink-missing\" href=\"https://tiddlywiki.com/static/TiddlyWikiDev.html\">TiddlyWikiDev\u003C/a> group for developers: \u003Ca class=\"tc-tiddlylink-external\" href=\"http://groups.google.com/group/TiddlyWikiDev\" rel=\"noopener noreferrer\" target=\"_blank\">http://groups.google.com/group/TiddlyWikiDev\u003C/a>\u003Cblockquote>\u003Cp>Note that you do not need a Google Account to join the discussion groups. Subscribe by sending an email to \u003Ca class=\"tc-tiddlylink-external\" href=\"mailto:tiddlywiki
{"title":"TiddlyWiki RSS/Atom feed","type":"text/x-markdown","text":"I've just started doing some research as to whether this is possible.\n\n[https://github.com/dullroar/TW5-atomfeed](https://github.com/dullroar/TW5-atomfeed)\n\n[https://boycook.wordpress.com/2007/09/26/rsswiki-or-tiddlyblog-pulling-rss-feeds-into-your-tiddlywiki/](https://boycook.wordpress.com/2007/09/26/rsswiki-or-tiddlyblog-pulling-rss-feeds-into-your-tiddlywiki/)\n\n[https://github.com/sycom/TiddlyWiki-Plugins/tree/master/plugins/sycom/atom-feed](https://github.com/sycom/TiddlyWiki-Plugins/tree/master/plugins/sycom/atom-feed)\n\n[https://www.comp.nus.edu.sg/~henz/students/shangshang.pdf](https://www.comp.nus.edu.sg/~henz/students/shangshang.pdf)","created":"20200324110857752","modified":"20200324111254670","tags":"Tech"},
{"title":"TiddlyWiki5 RSS Feed Plugin","type":"text/x-markdown","text":"I'm still a bit unsure how to generate a RSS feed from Tiddlywiki. It seems possible but I'll collect info here as I find out more.\n\nI'm not using the Nodejs server for this TiddlyWiki at the moment and this might be a problem for creating RSS feeds. I literally just save as and then commit to git (I'll write more about this in the future). \n\n- https://github.com/dullroar/TW5-atomfeed\n- https://github.com/dullroar/TW5-atomfeed/issues/9","created":"20200630235746945","modified":"20200701000123575","tags":"Tech"},
{"title":"Tunes April 2021","type":"text/x-markdown","text":"- https://bandcamp.com/sevan\n- https://charliemay.bandcamp.com/track/behemoth\n- https://sirsounds.com/album/sirs-s-4-in-the-morning\n- https://andybutler.bandcamp.com\n- https://music.hessleaudio.com/track/fluo\n- https://efdemindial.bandcamp.com/album/decay-versions-pt-2","created":"20210412105350551","modified":"20210412105453998","tags":"Music"},
{"title":"Tunes March 2021","type":"text/x-markdown","text":"## The Orb - Little Fluffy Clouds\nhttps://www.youtube.com/watch?v=FHixChYgGRI\n\n## Nicolas Godin - The Foundation ft. Cola Boyy\nhttps://www.youtube.com/watch?v=5N6y7JrebLI\n\n## Bailey - Intelligent Drum & Bass (1996)\nhttps://www.youtube.com/watch?v=Yc5iPDvmEpE\n\n## Hard Wax In-store: Calibre\nhttps://www.youtube.com/watch?v=88VYTu6zRqg","created":"20210309145059458","modified":"20210309145247685","tags":"Music"},
{"title":"UK Ham Radio Course Materials","type":"text/x-markdown","text":"https://www.essexham.co.uk/train/foundation-online-resources/","created":"20200724122539358","modified":"20200724122609637","tags":"P2P"},
{"title":"Unemployed Workers Centres","type":"text/x-markdown","text":"https://www.tuc.org.uk/sites/default/files/extras/hands_up_for_uwcs.pdf","created":"20210309145409789","modified":"20210309145431231","tags":"Organising"},
{"title":"Untitled","type":"text/plain","text":"https://cooperationbirmingham.org.uk/"},
{"title":"Untitled 1","type":"text/plain","text":"//Edit: I need to work out how pdfs work in TiddlyWiki https://tiddlywiki.com/prerelease/static/How%2520to%2520embed%2520PDF%2520and%2520other%2520documents.html //"},
{"title":"Update all packages using opkg on OpenWRT","type":"text/x-markdown","text":"`opkg list-upgradable | cut -f 1 -d ' ' | xargs opkg upgrade`","created":"20201106011309877","modified":"20201106011354678","tags":""},
{"title":"Usability Testing (UX)","type":"text/x-markdown","text":"I found a really good article about running usability testing study. We've been following it at work to great effect.\n\nhttps://samuelhewitt.com/blog/2019-08-27-how-to-run-a-usability-test-on-free-software-linux","created":"20200702112414199","modified":"20200702112544535","tags":"Tech"},
{"title":"Web Image Scrubber","type":"text/x-markdown","text":"> This is a tool for anonymizing photographs taken at protests.\n> \n> It will remove identifying metadata (Exif data) from photographs, and also allow you to selectively blur parts of the image to cover faces and other identifiable information.\n\n- https://everestpipkin.github.io/image-scrubber/\n- https://github.com/everestpipkin/image-scrubber","created":"20200607181106692","modified":"20200607181213782","tags":"Organising Tech"},
{"title":"Welcome to my blog!","type":"text/x-markdown","text":"This is an experimental attempt to create a \"walkaway wiki\" as referenced in Cory Doctorow's book **Walkaway**. It is hosted on the Peer to Peer web and then mirrored to the old web. It's nothing fancy. I will just be using it as a blog and mind dump for my solarpunk explorations. Enjoy.\n\nYou can find it on dat:\n\n[dat://510b9f5baf4e71269d2681ad4ca5f8186769fcddfee779d12ad339b5eca608cd/](dat://510b9f5baf4e71269d2681ad4ca5f8186769fcddfee779d12ad339b5eca608cd/)\n\nOr on the old web:\n\n[https://kawaiipunk.xyz/](https://kawaiipunk.xyz/)\n\n## Technologies used\n- [TiddlyWiki](https://tiddlywiki.com/)\n- [Dat](https://dat.foundation/)\n- [Beaker Browser](https://beakerbrowser.com/)\n- [Homebase](https://github.com/beakerbrowser/homebase/)\n- [Git](https://git.autonomic.zone/kawaiipunk/walkaway-wiki)\n","created":"20200326210914071","modified":"20200326210937689","tags":""},
{"title":"What I'm listening to December 2020","type":"text/x-markdown","text":"https://drycleaning.bandcamp.com/album/sweet-princess-ep\n\nhttps://drycleaning.bandcamp.com/track/scratchcard-lanyard\n\nhttps://saysueme.bandcamp.com/album/say-sue-me\n\nhttps://www.eff.org/deeplinks/2020/11/podcast-episode-control-over-users-competitors-and-critics\n\nTwain - Royal Road\nhttps://www.youtube.com/watch?v=7iGJjC2C_5w&feature=youtu.be","created":"20201201224553380","modified":"20201201224718250","tags":"Music Podcasts"},
{"title":"What Is De-essing? The Dos and Donts of Using a De-esser","type":"text/x-markdown","text":"https://www.izotope.com/en/learn/the-dos-and-donts-of-de-essing.html\n\n> De-essing is the process of attenuating or reducing sibilance, or harsh high-frequency sounds that come from dialogue or vocals using the letters S, F, X, SH, and soft Cs. \n> \n> Its often a necessary process when mixing audio, but its rarely easy—especially when youre just getting started. Many factors contribute to the complex nature of de-essing, from the way split-band processors can impact the character of a sound, to the manner in which the human voice can change from sibilance to sibilance.\n> \n> With this in mind, I found it necessary for my practice to develop a list of dos and donts. Its my pleasure to share it with you now. In this article, well discuss what de-essing is, how to use a de-esser, and other de-essing tips.","created":"20201201225414836","modified":"20201201225503521","tags":"Music [[Music Production]]"},
{"title":"Whats App terms of service change","type":"text/x-markdown","text":"https://arstechnica.com/tech-policy/2021/01/whatsapp-users-must-share-their-data-with-facebook-or-stop-using-the-app/","created":"20210109171542923","modified":"20210109171611845","tags":"Tech Security"},
{"title":"WhatsApp Vulnrebility April 2021","type":"text/x-markdown","text":"- https://www.forbes.com/sites/zakdoffman/2021/04/10/shock-new-warning-for-millions-of-whatsapp-users-on-apple-iphone-and-google-android-phones/\n- https://www.forbes.com/sites/zakdoffman/2021/04/10/stop-using-facebook-messenger-on-your-apple-iphone-or-google-android-phone/","created":"20210414123554655","modified":"20210414123636623","tags":"Tech Security"},
{"title":"Where to get camping gear in UK","type":"text/x-markdown","text":"- https://alpkit.com/\n- https://www.backpackinglight.co.uk/\n- https://www.gooutdoors.co.uk/","created":"20200705152431940","modified":"20200705152600382","tags":"Lists"},
{"title":"Wild Food UK","type":"text/x-markdown","text":"I found a site that has a useful mushroom foraging guide:\n\n- https://www.wildfooduk.com/mushroom-guide/\n- https://www.wildfooduk.com/mushroom-guide/chicken-of-the-woods/","created":"20200702112028819","modified":"20200702112112272","tags":"Ecology Food"},
{"title":"Wordpress Crowdfunding Plugin","type":"text/x-markdown","text":"Integrates with WooCommerce to give a Patreon style experience. \n\nhttps://www.themeum.com/product/wp-crowdfunding-plugin/","created":"20200724122118157","modified":"20200724122217131","tags":"Social Tech"},
{"title":"Z-TRITON Solarpunk Bike/Boat/Home","type":"text/x-markdown","text":"> House-boat-trike or a tiny amphibious home / camper that allows you to travel over land and water. Perfect for either expeditions around the world or for recreation - a weekend getaway deep in the nature. Equipped with electric assistance it's an easy and fun ride both on land and water.\n\nhttps://zeltini.com/en/product/z-triton/","created":"20200607180946314","modified":"20200607181042069","tags":"Solarpunk"},
{"title":"Zines! Zines! Zines!","type":"text/x-markdown","text":"I found a huge international list of zines providers.\n\nhttps://penfightdistro.com/resources/zines/","created":"20200702113234286","modified":"20200703210918185","tags":"Books Social"},
{"title":"Zoom MS-70CDR Multi-Effects Pedal","type":"text/x-markdown","text":"My friend had this and it was really good. \n\n- https://www.pmtonline.co.uk/zoom-ms70cdr-multi-effects-pedal\n\n> This compact pedal offer 86 custom guitar and bass effects, serving them up in an easy-to-use interface which includes a built in chromatic tuner and versatile power optioning including USB functionality.","created":"20200716122800236","modified":"20200716122910900","tags":"Tech Music"}
]</script><div id="storeArea" style="display:none;"></div>
<!--~~ Library modules ~~-->
<div id="libraryModules" style="display:none;">
<script data-tiddler-library="yes" data-tiddler-title="$:/library/sjcl.js" data-tiddler-type="application/javascript" type="text/javascript">"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
sjcl.cipher.aes=function(a){this.s[0][0][0]||this.O();var b,c,d,e,f=this.s[0][4],g=this.s[1];b=a.length;var h=1;if(4!==b&&6!==b&&8!==b)throw new sjcl.exception.invalid("invalid aes key size");this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
255]]};
sjcl.cipher.aes.prototype={encrypt:function(a){return t(this,a,0)},decrypt:function(a){return t(this,a,1)},s:[[[],[],[],[],[]],[[],[],[],[],[]]],O:function(){var a=this.s[0],b=this.s[1],c=a[4],d=b[4],e,f,g,h=[],k=[],l,n,m,p;for(e=0;0x100>e;e++)k[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=l||1,g=k[g]||1)for(m=g^g<<1^g<<2^g<<3^g<<4,m=m>>8^m&255^99,c[f]=m,d[m]=f,n=h[e=h[l=h[f]]],p=0x1010101*n^0x10001*e^0x101*l^0x1010100*f,n=0x101*h[m]^0x1010100*m,e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8;for(e=
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
function t(a,b,c){if(4!==b.length)throw new sjcl.exception.invalid("invalid aes block size");var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,k,l,n=d.length/4-2,m,p=4,r=[0,0,0,0];h=a.s[c];a=h[0];var q=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m<n;m++)h=a[e>>>24]^q[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],k=a[f>>>24]^q[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],l=a[g>>>24]^q[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^q[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=k,g=l;for(m=
0;4>m;m++)r[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return r}
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.$(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b=b&31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
c},$:function(a,b,c,d){var e;e=0;for(void 0===d&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},i:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]},byteswapM:function(a){var b,c;for(b=0;b<a.length;++b)c=a[b],a[b]=c>>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}};
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++)0===(d&3)&&(e=a[d/4]),b+=String.fromCharCode(e>>>8>>>8>>>8),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++)d=d<<8|a.charCodeAt(c),3===(c&3)&&(b.push(d),d=0);c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a=a+"00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,4*d)}};
sjcl.codec.base32={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",X:"0123456789ABCDEFGHIJKLMNOPQRSTUV",BITS:32,BASE:5,REMAINING:27,fromBits:function(a,b,c){var d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f="",g=0,h=sjcl.codec.base32.B,k=0,l=sjcl.bitArray.bitLength(a);c&&(h=sjcl.codec.base32.X);for(c=0;f.length*d<l;)f+=h.charAt((k^a[c]>>>g)>>>e),g<d?(k=a[c]<<d-g,g+=e,c++):(k<<=d,g-=d);for(;f.length&7&&!b;)f+="=";return f},toBits:function(a,b){a=a.replace(/\s|=/g,"").toUpperCase();var c=sjcl.codec.base32.BITS,
d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f=[],g,h=0,k=sjcl.codec.base32.B,l=0,n,m="base32";b&&(k=sjcl.codec.base32.X,m="base32hex");for(g=0;g<a.length;g++){n=k.indexOf(a.charAt(g));if(0>n){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}throw new sjcl.exception.invalid("this isn't "+m+"!");}h>e?(h-=e,f.push(l^n>>>h),l=n<<c-h):(h+=d,l^=n<<c-h)}h&56&&f.push(sjcl.bitArray.partial(h&56,l,1));return f}};
sjcl.codec.base32hex={fromBits:function(a,b){return sjcl.codec.base32.fromBits(a,b,1)},toBits:function(a){return sjcl.codec.base32.toBits(a,1)}};
sjcl.codec.base64={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.B,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=f.charAt((g^a[c]>>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.B,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;d<a.length;d++){h=f.indexOf(a.charAt(d));
if(0>h)throw new sjcl.exception.invalid("this isn't base64!");26<e?(e-=26,c.push(g^h>>>e),g=h<<32-e):(e+=6,g^=h<<32-e)}e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.O();a?(this.F=a.F.slice(0),this.A=a.A.slice(0),this.l=a.l):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.F=this.Y.slice(0);this.A=[];this.l=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.A=sjcl.bitArray.concat(this.A,a);b=this.l;a=this.l=b+sjcl.bitArray.bitLength(a);if(0x1fffffffffffff<a)throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");if("undefined"!==typeof Uint32Array){var d=new Uint32Array(c),e=0;for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,d.subarray(16*e,
16*(e+1))),e+=1;c.splice(0,16*e)}else for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,c.splice(0,16));return this},finalize:function(){var a,b=this.A,c=this.F,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.l/0x100000000));for(b.push(this.l|0);b.length;)u(this,b.splice(0,16));this.reset();return c},Y:[],b:[],O:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}for(var b=0,c=2,d,e;64>b;c++){e=!0;for(d=2;d*d<=c;d++)if(0===c%d){e=
!1;break}e&&(8>b&&(this.Y[b]=a(Math.pow(c,.5))),this.b[b]=a(Math.pow(c,1/3)),b++)}}};
function u(a,b){var c,d,e,f=a.F,g=a.b,h=f[0],k=f[1],l=f[2],n=f[3],m=f[4],p=f[5],r=f[6],q=f[7];for(c=0;64>c;c++)16>c?d=b[c]:(d=b[c+1&15],e=b[c+14&15],d=b[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+b[c&15]+b[c+9&15]|0),d=d+q+(m>>>6^m>>>11^m>>>25^m<<26^m<<21^m<<7)+(r^m&(p^r))+g[c],q=r,r=p,p=m,m=n+d|0,n=l,l=k,k=h,h=d+(k&l^n&(k^l))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+h|0;f[1]=f[1]+k|0;f[2]=f[2]+l|0;f[3]=f[3]+n|0;f[4]=f[4]+m|0;f[5]=f[5]+p|0;f[6]=f[6]+r|0;f[7]=
f[7]+q|0}
sjcl.mode.ccm={name:"ccm",G:[],listenProgress:function(a){sjcl.mode.ccm.G.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.G.indexOf(a);-1<a&&sjcl.mode.ccm.G.splice(a,1)},fa:function(a){var b=sjcl.mode.ccm.G.slice(),c;for(c=0;c<b.length;c+=1)b[c](a)},encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,k=h.bitLength(c)/8,l=h.bitLength(g)/8;e=e||64;d=d||[];if(7>k)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;4>f&&l>>>8*f;f++);f<15-k&&(f=15-k);c=h.clamp(c,
8*(15-f));b=sjcl.mode.ccm.V(a,b,c,d,e,f);g=sjcl.mode.ccm.C(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),k=f.clamp(b,h-e),l=f.bitSlice(b,h-e),h=(h-e)/8;if(7>g)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));k=sjcl.mode.ccm.C(a,k,c,l,e,b);a=sjcl.mode.ccm.V(a,k.data,c,d,e,b);if(!f.equal(k.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");
return k.data},na:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,k=h.i;d=[h.partial(8,(b.length?64:0)|d-2<<2|f-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length)for(c=h.bitLength(b)/8,65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c])),g=h.concat(g,b),b=0;b<g.length;b+=4)d=a.encrypt(k(d,g.slice(b,b+4).concat([0,0,0])));return d},V:function(a,b,c,d,e,f){var g=sjcl.bitArray,h=g.i;e/=8;if(e%2||4>e||16<e)throw new sjcl.exception.invalid("ccm: invalid tag length");
if(0xffffffff<d.length||0xffffffff<b.length)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");c=sjcl.mode.ccm.na(a,d,c,e,g.bitLength(b)/8,f);for(d=0;d<b.length;d+=4)c=a.encrypt(h(c,b.slice(d,d+4).concat([0,0,0])));return g.clamp(c,8*e)},C:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var k=b.length,l=h.bitLength(b),n=k/50,m=n;c=h.concat([h.partial(8,f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!k)return{tag:d,data:[]};for(g=0;g<k;g+=4)g>n&&(sjcl.mode.ccm.fa(g/
k),n+=m),c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,l)}}};
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.S,k=sjcl.bitArray,l=k.i,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4)m=b.slice(g,g+4),n=l(n,m),p=p.concat(l(c,a.encrypt(l(c,m)))),c=h(c);m=b.slice(g);b=k.bitLength(m);g=a.encrypt(l(c,[0,0,0,b]));m=k.clamp(l(m.concat([0,0,0]),g),b);n=l(n,l(m.concat([0,0,0]),g));n=a.encrypt(l(n,l(c,h(c))));
d.length&&(n=l(n,f?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(k.concat(m,k.clamp(n,e)))},decrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.S,h=sjcl.bitArray,k=h.i,l=[0,0,0,0],n=g(a.encrypt(c)),m,p,r=sjcl.bitArray.bitLength(b)-e,q=[];d=d||[];for(c=0;c+4<r/32;c+=4)m=k(n,a.decrypt(k(n,b.slice(c,c+4)))),l=k(l,m),q=q.concat(m),n=g(n);p=r-32*c;m=a.encrypt(k(n,[0,0,0,p]));m=k(m,h.clamp(b.slice(c),p).concat([0,
0,0]));l=k(l,m);l=a.encrypt(k(l,k(n,g(n))));d.length&&(l=k(l,f?d:sjcl.mode.ocb2.pmac(a,d)));if(!h.equal(h.clamp(l,e),h.bitSlice(b,r)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return q.concat(h.clamp(m,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.S,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),g=f(g,a.encrypt(f(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);
return a.encrypt(f(d(f(h,d(h))),g))},S:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.C(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.C(!1,a,f,d,c,e);if(!g.equal(a.tag,b))throw new sjcl.exception.corrupt("gcm: tag doesn't match");return a.data},ka:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.i;e=[0,0,
0,0];f=b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0<d;d--)f[d]=f[d]>>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},j:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;d<e;d+=4)b[0]^=0xffffffff&c[d],b[1]^=0xffffffff&c[d+1],b[2]^=0xffffffff&c[d+2],b[3]^=0xffffffff&c[d+3],b=sjcl.mode.gcm.ka(b,a);return b},C:function(a,b,c,d,e,f){var g,h,k,l,n,m,p,r,q=sjcl.bitArray;m=c.length;p=q.bitLength(c);r=q.bitLength(d);h=q.bitLength(e);
g=b.encrypt([0,0,0,0]);96===h?(e=e.slice(0),e=q.concat(e,[1])):(e=sjcl.mode.gcm.j(g,[0,0,0,0],e),e=sjcl.mode.gcm.j(g,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.j(g,[0,0,0,0],d);n=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.j(g,h,c));for(l=0;l<m;l+=4)n[3]++,k=b.encrypt(n),c[l]^=k[0],c[l+1]^=k[1],c[l+2]^=k[2],c[l+3]^=k[3];c=q.clamp(c,p);a&&(d=sjcl.mode.gcm.j(g,h,c));a=[Math.floor(r/0x100000000),r&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.j(g,d,a);k=b.encrypt(e);
d[0]^=k[0];d[1]^=k[1];d[2]^=k[2];d[3]^=k[3];return{tag:q.bitSlice(d,0,f),data:c}}};sjcl.misc.hmac=function(a,b){this.W=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.w=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.w[0].update(c[0]);this.w[1].update(c[1]);this.R=new b(this.w[0])};
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){if(this.aa)throw new sjcl.exception.invalid("encrypt on already updated hmac called!");this.update(a);return this.digest(a)};sjcl.misc.hmac.prototype.reset=function(){this.R=new this.W(this.w[0]);this.aa=!1};sjcl.misc.hmac.prototype.update=function(a){this.aa=!0;this.R.update(a)};sjcl.misc.hmac.prototype.digest=function(){var a=this.R.finalize(),a=(new this.W(this.w[1])).update(a).finalize();this.reset();return a};
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E4;if(0>d||0>c)throw new sjcl.exception.invalid("invalid params to pbkdf2");"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,k,l=[],n=sjcl.bitArray;for(k=1;32*l.length<(d||1);k++){e=f=a.encrypt(n.concat(b,[k]));for(g=1;g<c;g++)for(f=a.encrypt(f),h=0;h<f.length;h++)e[h]^=f[h];l=l.concat(e)}d&&(l=n.clamp(l,d));return l};
sjcl.prng=function(a){this.c=[new sjcl.hash.sha256];this.m=[0];this.P=0;this.H={};this.N=0;this.U={};this.Z=this.f=this.o=this.ha=0;this.b=[0,0,0,0,0,0,0,0];this.h=[0,0,0,0];this.L=void 0;this.M=a;this.D=!1;this.K={progress:{},seeded:{}};this.u=this.ga=0;this.I=1;this.J=2;this.ca=0x10000;this.T=[0,48,64,96,128,192,0x100,384,512,768,1024];this.da=3E4;this.ba=80};
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;if(d===this.u)throw new sjcl.exception.notReady("generator isn't seeded");if(d&this.J){d=!(d&this.I);e=[];var f=0,g;this.Z=e[0]=(new Date).valueOf()+this.da;for(g=0;16>g;g++)e.push(0x100000000*Math.random()|0);for(g=0;g<this.c.length&&(e=e.concat(this.c[g].finalize()),f+=this.m[g],this.m[g]=0,d||!(this.P&1<<g));g++);this.P>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.m.push(0));this.f-=f;f>this.o&&(this.o=
f);this.P++;this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.L=new sjcl.cipher.aes(this.b);for(d=0;4>d&&(this.h[d]=this.h[d]+1|0,!this.h[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.ca&&y(this),e=z(this),c.push(e[0],e[1],e[2],e[3]);y(this);return c.slice(0,a)},setDefaultParanoia:function(a,b){if(0===a&&"Setting paranoia=0 will ruin your security; use it only for testing"!==b)throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");this.M=a},addEntropy:function(a,
b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.H[c],h=this.isReady(),k=0;d=this.U[c];void 0===d&&(d=this.U[c]=this.ha++);void 0===g&&(g=this.H[c]=0);this.H[c]=(this.H[c]+1)%this.c.length;switch(typeof a){case "number":void 0===b&&(b=1);this.c[g].update([d,this.N++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if("[object Uint32Array]"===c){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else for("[object Array]"!==c&&(k=1),c=0;c<a.length&&!k;c++)"number"!==typeof a[c]&&
(k=1);if(!k){if(void 0===b)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,e=e>>>1;this.c[g].update([d,this.N++,2,b,f,a.length].concat(a))}break;case "string":void 0===b&&(b=a.length);this.c[g].update([d,this.N++,3,b,f,a.length]);this.c[g].update(a);break;default:k=1}if(k)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.m[g]+=b;this.f+=b;h===this.u&&(this.isReady()!==this.u&&A("seeded",Math.max(this.o,this.f)),A("progress",this.getProgress()))},
isReady:function(a){a=this.T[void 0!==a?a:this.M];return this.o&&this.o>=a?this.m[0]>this.ba&&(new Date).valueOf()>this.Z?this.J|this.I:this.I:this.f>=a?this.J|this.u:this.u},getProgress:function(a){a=this.T[a?a:this.M];return this.o>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.D){this.a={loadTimeCollector:B(this,this.ma),mouseCollector:B(this,this.oa),keyboardCollector:B(this,this.la),accelerometerCollector:B(this,this.ea),touchCollector:B(this,this.qa)};if(window.addEventListener)window.addEventListener("load",
this.a.loadTimeCollector,!1),window.addEventListener("mousemove",this.a.mouseCollector,!1),window.addEventListener("keypress",this.a.keyboardCollector,!1),window.addEventListener("devicemotion",this.a.accelerometerCollector,!1),window.addEventListener("touchmove",this.a.touchCollector,!1);else if(document.attachEvent)document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector);else throw new sjcl.exception.bug("can't attach event");
this.D=!0}},stopCollectors:function(){this.D&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,!1),window.removeEventListener("mousemove",this.a.mouseCollector,!1),window.removeEventListener("keypress",this.a.keyboardCollector,!1),window.removeEventListener("devicemotion",this.a.accelerometerCollector,!1),window.removeEventListener("touchmove",this.a.touchCollector,!1)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",
this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.D=!1)},addEventListener:function(a,b){this.K[a][this.ga++]=b},removeEventListener:function(a,b){var c,d,e=this.K[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;c<f.length;c++)d=f[c],delete e[d]},la:function(){C(this,1)},oa:function(a){var b,c;try{b=a.x||a.clientX||a.offsetX||0,c=a.y||a.clientY||a.offsetY||0}catch(d){c=b=0}0!=b&&0!=c&&this.addEntropy([b,c],2,"mouse");C(this,0)},qa:function(a){a=
a.touches[0]||a.changedTouches[0];this.addEntropy([a.pageX||a.clientX,a.pageY||a.clientY],1,"touch");C(this,0)},ma:function(){C(this,2)},ea:function(a){a=a.accelerationIncludingGravity.x||a.accelerationIncludingGravity.y||a.accelerationIncludingGravity.z;if(window.orientation){var b=window.orientation;"number"===typeof b&&this.addEntropy(b,1,"accelerometer")}a&&this.addEntropy(a,2,"accelerometer");C(this,0)}};
function A(a,b){var c,d=sjcl.random.K[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}function C(a,b){"undefined"!==typeof window&&window.performance&&"function"===typeof window.performance.now?a.addEntropy(window.performance.now(),b,"loadtime"):a.addEntropy((new Date).valueOf(),b,"loadtime")}function y(a){a.b=z(a).concat(z(a));a.L=new sjcl.cipher.aes(a.b)}function z(a){for(var b=0;4>b&&(a.h[b]=a.h[b]+1|0,!a.h[b]);b++);return a.L.encrypt(a.h)}
function B(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
a:try{var D,E,F,G;if(G="undefined"!==typeof module&&module.exports){var H;try{H=require("crypto")}catch(a){H=null}G=E=H}if(G&&E.randomBytes)D=E.randomBytes(128),D=new Uint32Array((new Uint8Array(D)).buffer),sjcl.random.addEntropy(D,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){F=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(F);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(F);
else break a;sjcl.random.addEntropy(F,1024,"crypto['getRandomValues']")}}catch(a){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(a))}
sjcl.json={defaults:{v:1,iter:1E4,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},ja:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.g({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.g(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
4<f.iv.length)throw new sjcl.exception.invalid("json encrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(f.adata=c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.g(d,f);d.key=a;f.ct="ccm"===f.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&
b instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.encrypt(g,b,f.iv,c,f.ts):sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return f},encrypt:function(a,b,c,d){var e=sjcl.json,f=e.ja.apply(e,arguments);return e.encode(f)},ia:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.g(e.g(e.g({},e.defaults),b),c,!0);var f,g;f=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===
typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4<b.iv.length)throw new sjcl.exception.invalid("json decrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,b),a=g.key.slice(0,b.ks/32),b.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.secretKey&&(a=a.unkem(sjcl.codec.base64.toBits(b.kemtag)).slice(0,b.ks/32));"string"===typeof f&&(f=sjcl.codec.utf8String.toBits(f));g=new sjcl.cipher[b.cipher](a);f="ccm"===
b.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&b.ct instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.decrypt(g,b.ct,b.iv,b.tag,f,b.ts):sjcl.mode[b.mode].decrypt(g,b.ct,b.iv,f,b.ts);e.g(d,b);d.key=a;return 1===c.raw?f:sjcl.codec.utf8String.fromBits(f)},decrypt:function(a,b,c,d){var e=sjcl.json;return e.ia(a,e.decode(b),c,d)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+
b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],0)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");
null!=d[3]?b[d[2]]=parseInt(d[3],10):null!=d[4]?b[d[2]]=d[2].match(/^(ct|adata|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4]):null!=d[5]&&(b[d[2]]="true"===d[5])}return b},g:function(a,b,c){void 0===a&&(a={});if(void 0===b)return a;for(var d in b)if(b.hasOwnProperty(d)){if(c&&void 0!==a[d]&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},sa:function(a,b){var c={},d;for(d in a)a.hasOwnProperty(d)&&a[d]!==b[d]&&(c[d]=a[d]);return c},ra:function(a,
b){var c={},d;for(d=0;d<b.length;d++)void 0!==a[b[d]]&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.pa={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.pa,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=void 0===b.salt?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl});
</script>
</div>
<!--~~ Boot kernel prologue ~~-->
<div id="bootKernelPrefix" style="display:none;">
<script data-tiddler-title="$:/boot/bootprefix.js" data-tiddler-type="application/javascript" type="text/javascript">/*\
title: $:/boot/bootprefix.js
type: application/javascript
This file sets up the globals that need to be available when JavaScript modules are executed in the browser. The overall sequence is:
# BootPrefix.js
# <module definitions>
# Boot.js
See Boot.js for further details of the boot process.
\*/
var _bootprefix = (function($tw) {
"use strict";
$tw = $tw || Object.create(null);
$tw.boot = $tw.boot || Object.create(null);
// Detect platforms
if(!("browser" in $tw)) {
$tw.browser = typeof(window) !== "undefined" ? {} : null;
}
if(!("node" in $tw)) {
$tw.node = typeof(process) === "object" ? {} : null;
}
if(!("nodeWebKit" in $tw)) {
$tw.nodeWebKit = $tw.node && global.window && global.window.nwDispatcher ? {} : null;
}
// Set default boot tasks
$tw.boot.tasks = {
trapErrors: !!($tw.browser && !$tw.node),
readBrowserTiddlers: !!($tw.browser && !$tw.node)
};
/*
Information about each module is kept in an object with these members:
moduleType: type of module
definition: object, function or string defining the module; see below
exports: exports of the module, filled in after execution
The `definition` can be of several types:
* An object can be used to directly specify the exports of the module
* A function with the arguments `module,require,exports` that returns `exports`
* A string function body with the same arguments
Each moduleInfo object is stored in two hashmaps: $tw.modules.titles and $tw.modules.types. The first is indexed by title and the second is indexed by type and then title
*/
$tw.modules = {
titles: {}, // hashmap by module name of moduleInfo
types: {} // hashmap by module type and then name of moduleInfo
};
/*
Define a JavaScript tiddler module for later execution
moduleName: name of module being defined
moduleType: type of module
definition: module definition; see discussion above
*/
$tw.modules.define = function(moduleName,moduleType,definition) {
// Create the moduleInfo
var moduleInfo = {
moduleType: moduleType,
definition: definition,
exports: undefined
};
// If the definition is already an object we can use it as the exports
if(typeof moduleInfo.definition === "object") {
moduleInfo.exports = definition;
}
// Store the module in the titles hashmap
if(Object.prototype.hasOwnProperty.call($tw.modules.titles,moduleName)) {
console.log("Warning: Redefined module - " + moduleName);
}
$tw.modules.titles[moduleName] = moduleInfo;
// Store the module in the types hashmap
if(!Object.prototype.hasOwnProperty.call($tw.modules.types,moduleType)) {
$tw.modules.types[moduleType] = {};
}
if(Object.prototype.hasOwnProperty.call($tw.modules.types[moduleType],moduleName)) {
console.log("Warning: Redefined module - " + moduleName);
}
$tw.modules.types[moduleType][moduleName] = moduleInfo;
};
/*
External JavaScript can populate this array before calling boot.js in order to preload tiddlers
*/
$tw.preloadTiddlers = $tw.preloadTiddlers || [];
/*
Convenience function for pushing a tiddler onto the preloading array
*/
$tw.preloadTiddler = function(fields) {
$tw.preloadTiddlers.push(fields);
};
/*
Convenience function for pushing an array of tiddlers onto the preloading array
*/
$tw.preloadTiddlerArray = function(fieldsArray) {
$tw.preloadTiddlers.push.apply($tw.preloadTiddlers,fieldsArray);
};
return $tw;
});
if(typeof(exports) === "undefined") {
// Set up $tw global for the browser
window.$tw = _bootprefix(window.$tw);
} else {
// Export functionality as a module
exports.bootprefix = _bootprefix;
}
2022-04-14 23:41:27 +00:00
//# sourceURL=$:/boot/bootprefix.js
</script>
</div>
<!--~~ Boot kernel ~~-->
<div id="bootKernel" style="display:none;">
<script data-tiddler-title="$:/boot/boot.js" data-tiddler-type="application/javascript" type="text/javascript">/*\
title: $:/boot/boot.js
type: application/javascript
The main boot kernel for TiddlyWiki. This single file creates a barebones TW environment that is just sufficient to bootstrap the modules containing the main logic of the application.
On the server this file is executed directly to boot TiddlyWiki. In the browser, this file is packed into a single HTML file.
\*/
var _boot = (function($tw) {
/*jslint node: true, browser: true */
/*global modules: false, $tw: false */
"use strict";
// Include bootprefix if we're not given module data
if(!$tw) {
$tw = require("./bootprefix.js").bootprefix();
}
$tw.utils = $tw.utils || Object.create(null);
/////////////////////////// Standard node.js libraries
var fs, path, vm;
if($tw.node) {
fs = require("fs");
path = require("path");
vm = require("vm");
}
/////////////////////////// Utility functions
$tw.boot.log = function(str) {
$tw.boot.logMessages = $tw.boot.logMessages || [];
$tw.boot.logMessages.push(str);
}
/*
Check if an object has a property
*/
$tw.utils.hop = function(object,property) {
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
};
/*
Determine if a value is an array
*/
$tw.utils.isArray = function(value) {
return Object.prototype.toString.call(value) == "[object Array]";
};
/*
Check if an array is equal by value and by reference.
*/
$tw.utils.isArrayEqual = function(array1,array2) {
if(array1 === array2) {
return true;
}
array1 = array1 || [];
array2 = array2 || [];
if(array1.length !== array2.length) {
return false;
}
return array1.every(function(value,index) {
return value === array2[index];
});
};
2022-04-14 23:41:27 +00:00
/*
Add an entry to a sorted array if it doesn't already exist, while maintaining the sort order
*/
$tw.utils.insertSortedArray = function(array,value) {
var low = 0, high = array.length - 1, mid, cmp;
while(low <= high) {
mid = (low + high) >> 1;
cmp = value.localeCompare(array[mid]);
if(cmp > 0) {
low = mid + 1;
} else if(cmp < 0) {
high = mid - 1;
} else {
return array;
}
}
array.splice(low,0,value);
return array;
};
/*
Push entries onto an array, removing them first if they already exist in the array
array: array to modify (assumed to be free of duplicates)
value: a single value to push or an array of values to push
*/
$tw.utils.pushTop = function(array,value) {
var t,p;
if($tw.utils.isArray(value)) {
// Remove any array entries that are duplicated in the new values
if(value.length !== 0) {
if(array.length !== 0) {
if(value.length < array.length) {
for(t=0; t<value.length; t++) {
p = array.indexOf(value[t]);
if(p !== -1) {
array.splice(p,1);
}
}
} else {
for(t=array.length-1; t>=0; t--) {
p = value.indexOf(array[t]);
if(p !== -1) {
array.splice(t,1);
}
}
}
}
// Push the values on top of the main array
array.push.apply(array,value);
}
} else {
p = array.indexOf(value);
if(p !== -1) {
array.splice(p,1);
}
array.push(value);
}
return array;
};
/*
Determine if a value is a date
*/
$tw.utils.isDate = function(value) {
return Object.prototype.toString.call(value) === "[object Date]";
};
/*
Iterate through all the own properties of an object or array. Callback is invoked with (element,title,object)
*/
$tw.utils.each = function(object,callback) {
var next,f,length;
if(object) {
if(Object.prototype.toString.call(object) == "[object Array]") {
for (f=0, length=object.length; f<length; f++) {
next = callback(object[f],f,object);
if(next === false) {
break;
}
}
} else {
var keys = Object.keys(object);
for (f=0, length=keys.length; f<length; f++) {
var key = keys[f];
next = callback(object[key],key,object);
if(next === false) {
break;
}
}
}
}
};
/*
Helper for making DOM elements
tag: tag name
options: see below
Options include:
namespace: defaults to http://www.w3.org/1999/xhtml
attributes: hashmap of attribute values
style: hashmap of styles
text: text to add as a child node
children: array of further child nodes
innerHTML: optional HTML for element
class: class name(s)
document: defaults to current document
eventListeners: array of event listeners (this option won't work until $tw.utils.addEventListeners() has been loaded)
*/
$tw.utils.domMaker = function(tag,options) {
var doc = options.document || document;
var element = doc.createElementNS(options.namespace || "http://www.w3.org/1999/xhtml",tag);
if(options["class"]) {
element.className = options["class"];
}
if(options.text) {
element.appendChild(doc.createTextNode(options.text));
}
$tw.utils.each(options.children,function(child) {
element.appendChild(child);
});
if(options.innerHTML) {
element.innerHTML = options.innerHTML;
}
$tw.utils.each(options.attributes,function(attribute,name) {
element.setAttribute(name,attribute);
});
$tw.utils.each(options.style,function(value,name) {
element.style[name] = value;
});
if(options.eventListeners) {
$tw.utils.addEventListeners(element,options.eventListeners);
}
return element;
};
/*
Display an error and exit
*/
$tw.utils.error = function(err) {
// Prepare the error message
var errHeading = ( $tw.language == undefined ? "Internal JavaScript Error" : $tw.language.getString("InternalJavaScriptError/Title") ),
promptMsg = ( $tw.language == undefined ? "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser" : $tw.language.getString("InternalJavaScriptError/Hint") );
// Log the error to the console
console.error($tw.node ? "\x1b[1;31m" + err + "\x1b[0m" : err);
if($tw.browser && !$tw.node) {
// Display an error message to the user
var dm = $tw.utils.domMaker,
heading = dm("h1",{text: errHeading}),
prompt = dm("div",{text: promptMsg, "class": "tc-error-prompt"}),
message = dm("div",{text: err, "class":"tc-error-message"}),
button = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
form = dm("form",{children: [heading,prompt,message,button], "class": "tc-error-form"});
document.body.insertBefore(form,document.body.firstChild);
form.addEventListener("submit",function(event) {
document.body.removeChild(form);
event.preventDefault();
return false;
},true);
return null;
} else if(!$tw.browser) {
// Exit if we're under node.js
process.exit(1);
}
};
/*
Use our custom error handler if we're in the browser
*/
if($tw.boot.tasks.trapErrors) {
window.onerror = function(errorMsg,url,lineNumber) {
$tw.utils.error(errorMsg);
return false;
};
}
/*
Extend an object with the properties from a list of source objects
*/
$tw.utils.extend = function(object /*, sourceObjectList */) {
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
if(source) {
for (var p in source) {
object[p] = source[p];
}
}
});
return object;
};
/*
Fill in any null or undefined properties of an object with the properties from a list of source objects. Each property that is an object is called recursively
*/
$tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
if(source) {
for (var p in source) {
if(object[p] === null || object[p] === undefined) {
object[p] = source[p];
}
if(typeof object[p] === "object" && typeof source[p] === "object") {
$tw.utils.deepDefaults(object[p],source[p]);
}
}
}
});
return object;
};
2022-04-14 23:41:27 +00:00
/*
Convert a URIComponent encoded string to a string safely
*/
$tw.utils.decodeURIComponentSafe = function(s) {
var v = s;
try {
v = decodeURIComponent(s);
} catch(e) {}
return v;
};
/*
Convert a URI encoded string to a string safely
*/
$tw.utils.decodeURISafe = function(s) {
var v = s;
try {
v = decodeURI(s);
} catch(e) {}
return v;
};
/*
Convert "&amp;" to &, "&nbsp;" to nbsp, "&lt;" to <, "&gt;" to > and "&quot;" to "
*/
$tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};
/*
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
*/
$tw.utils.getLocationHash = function() {
2022-04-14 23:41:27 +00:00
var href = window.location.href;
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(idx < href.length-1 && href[idx+1] === '#') {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
return href.substring(idx);
}
};
/*
Pad a string to a given length with "0"s. Length defaults to 2
*/
$tw.utils.pad = function(value,length) {
length = length || 2;
var s = value.toString();
if(s.length < length) {
s = "000000000000000000000000000".substr(0,length - s.length) + s;
}
return s;
};
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
$tw.utils.stringifyDate = function(value) {
return value.getUTCFullYear() +
$tw.utils.pad(value.getUTCMonth() + 1) +
$tw.utils.pad(value.getUTCDate()) +
$tw.utils.pad(value.getUTCHours()) +
$tw.utils.pad(value.getUTCMinutes()) +
$tw.utils.pad(value.getUTCSeconds()) +
$tw.utils.pad(value.getUTCMilliseconds(),3);
};
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
$tw.utils.parseDate = function(value) {
if(typeof value === "string") {
2022-04-14 23:41:27 +00:00
var negative = 1;
if(value.charAt(0) === "-") {
negative = -1;
value = value.substr(1);
}
var year = parseInt(value.substr(0,4),10) * negative,
d = new Date(Date.UTC(year,
parseInt(value.substr(4,2),10)-1,
parseInt(value.substr(6,2),10),
parseInt(value.substr(8,2)||"00",10),
parseInt(value.substr(10,2)||"00",10),
parseInt(value.substr(12,2)||"00",10),
parseInt(value.substr(14,3)||"000",10)));
2022-04-14 23:41:27 +00:00
d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822
return d;
} else if($tw.utils.isDate(value)) {
return value;
} else {
return null;
}
};
// Stringify an array of tiddler titles into a list string
$tw.utils.stringifyList = function(value) {
if($tw.utils.isArray(value)) {
var result = new Array(value.length);
for(var t=0, l=value.length; t<l; t++) {
var entry = value[t] || "";
if(entry.indexOf(" ") !== -1) {
result[t] = "[[" + entry + "]]";
} else {
result[t] = entry;
}
}
return result.join(" ");
} else {
return value || "";
}
};
// Parse a string array from a bracketted list. For example "OneTiddler [[Another Tiddler]] LastOne"
$tw.utils.parseStringArray = function(value, allowDuplicate) {
if(typeof value === "string") {
var memberRegExp = /(?:^|[^\S\xA0])(?:\[\[(.*?)\]\])(?=[^\S\xA0]|$)|([\S\xA0]+)/mg,
results = [], names = {},
match;
do {
match = memberRegExp.exec(value);
if(match) {
var item = match[1] || match[2];
if(item !== undefined && (!$tw.utils.hop(names,item) || allowDuplicate)) {
results.push(item);
names[item] = true;
}
}
} while(match);
return results;
} else if($tw.utils.isArray(value)) {
return value;
} else {
return null;
}
};
// Parse a block of name:value fields. The `fields` object is used as the basis for the return value
$tw.utils.parseFields = function(text,fields) {
fields = fields || Object.create(null);
text.split(/\r?\n/mg).forEach(function(line) {
if(line.charAt(0) !== "#") {
var p = line.indexOf(":");
if(p !== -1) {
var field = line.substr(0, p).trim(),
value = line.substr(p+1).trim();
if(field) {
fields[field] = value;
}
}
}
});
return fields;
};
2022-04-14 23:41:27 +00:00
// Safely parse a string as JSON
$tw.utils.parseJSONSafe = function(text,defaultJSON) {
try {
return JSON.parse(text);
} catch(e) {
if(typeof defaultJSON === "function") {
return defaultJSON(e);
} else {
return defaultJSON || {};
}
}
};
/*
Resolves a source filepath delimited with `/` relative to a specified absolute root filepath.
In relative paths, the special folder name `..` refers to immediate parent directory, and the
name `.` refers to the current directory
*/
$tw.utils.resolvePath = function(sourcepath,rootpath) {
// If the source path starts with ./ or ../ then it is relative to the root
if(sourcepath.substr(0,2) === "./" || sourcepath.substr(0,3) === "../" ) {
var src = sourcepath.split("/"),
root = rootpath.split("/");
// Remove the filename part of the root
root.splice(root.length-1,1);
// Process the source path bit by bit onto the end of the root path
while(src.length > 0) {
var c = src.shift();
if(c === "..") { // Slice off the last root entry for a double dot
if(root.length > 0) {
root.splice(root.length-1,1);
}
} else if(c !== ".") { // Ignore dots
root.push(c); // Copy other elements across
}
}
return root.join("/");
} else {
// If it isn't relative, just return the path
if(rootpath) {
var root = rootpath.split("/");
// Remove the filename part of the root
root.splice(root.length - 1, 1);
return root.join("/") + "/" + sourcepath;
} else {
return sourcepath;
}
}
};
/*
2022-04-14 23:41:27 +00:00
Parse a semantic version string into its constituent parts -- see https://semver.org
*/
$tw.utils.parseVersion = function(version) {
2022-04-14 23:41:27 +00:00
var match = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/.exec(version);
if(match) {
return {
version: match[1],
major: parseInt(match[2],10),
minor: parseInt(match[3],10),
patch: parseInt(match[4],10),
prerelease: match[5],
build: match[6]
};
} else {
return null;
}
};
2022-04-14 23:41:27 +00:00
/*
Returns +1 if the version string A is greater than the version string B, 0 if they are the same, and +1 if B is greater than A.
Missing or malformed version strings are parsed as 0.0.0
*/
$tw.utils.compareVersions = function(versionStringA,versionStringB) {
var defaultVersion = {
major: 0,
minor: 0,
patch: 0
},
versionA = $tw.utils.parseVersion(versionStringA) || defaultVersion,
versionB = $tw.utils.parseVersion(versionStringB) || defaultVersion,
diff = [
versionA.major - versionB.major,
versionA.minor - versionB.minor,
versionA.patch - versionB.patch
];
if((diff[0] > 0) || (diff[0] === 0 && diff[1] > 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] > 0)) {
return +1;
} else if((diff[0] < 0) || (diff[0] === 0 && diff[1] < 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] < 0)) {
return -1;
} else {
return 0;
}
};
/*
Returns true if the version string A is greater than the version string B. Returns true if the versions are the same
*/
$tw.utils.checkVersions = function(versionStringA,versionStringB) {
2022-04-14 23:41:27 +00:00
return $tw.utils.compareVersions(versionStringA,versionStringB) !== -1;
};
/*
Register file type information
options: {flags: flags,deserializerType: deserializerType}
flags:"image" for image types
deserializerType: defaults to type if not specified
*/
$tw.utils.registerFileType = function(type,encoding,extension,options) {
options = options || {};
if($tw.utils.isArray(extension)) {
$tw.utils.each(extension,function(extension) {
$tw.config.fileExtensionInfo[extension] = {type: type};
});
extension = extension[0];
} else {
$tw.config.fileExtensionInfo[extension] = {type: type};
}
$tw.config.contentTypeInfo[type] = {encoding: encoding, extension: extension, flags: options.flags || [], deserializerType: options.deserializerType || type};
};
/*
Given an extension, always access the $tw.config.fileExtensionInfo
using a lowercase extension only.
*/
$tw.utils.getFileExtensionInfo = function(ext) {
return ext ? $tw.config.fileExtensionInfo[ext.toLowerCase()] : null;
}
/*
Given an extension, get the correct encoding for that file.
defaults to utf8
*/
$tw.utils.getTypeEncoding = function(ext) {
var extensionInfo = $tw.utils.getFileExtensionInfo(ext),
type = extensionInfo ? extensionInfo.type : null,
typeInfo = type ? $tw.config.contentTypeInfo[type] : null;
return typeInfo ? typeInfo.encoding : "utf8";
};
/*
Run code globally with specified context variables in scope
*/
$tw.utils.evalGlobal = function(code,context,filename) {
var contextCopy = $tw.utils.extend(Object.create(null),context);
// Get the context variables as a pair of arrays of names and values
var contextNames = [], contextValues = [];
$tw.utils.each(contextCopy,function(value,name) {
contextNames.push(name);
contextValues.push(value);
});
// Add the code prologue and epilogue
code = "(function(" + contextNames.join(",") + ") {(function(){\n" + code + "\n;})();\nreturn exports;\n})\n";
// Compile the code into a function
var fn;
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
fn = vm.runInThisContext(code,filename);
}
// Call the function and return the exports
return fn.apply(null,contextValues);
};
/*
Run code in a sandbox with only the specified context variables in scope
*/
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename) {
var sandbox = $tw.utils.extend(Object.create(null),context);
vm.runInNewContext(code,sandbox,filename);
return sandbox.exports;
};
/*
Creates a PasswordPrompt object
*/
$tw.utils.PasswordPrompt = function() {
// Store of pending password prompts
this.passwordPrompts = [];
// Create the wrapper
this.promptWrapper = $tw.utils.domMaker("div",{"class":"tc-password-wrapper"});
document.body.appendChild(this.promptWrapper);
// Hide the empty wrapper
this.setWrapperDisplay();
};
/*
Hides or shows the wrapper depending on whether there are any outstanding prompts
*/
$tw.utils.PasswordPrompt.prototype.setWrapperDisplay = function() {
if(this.passwordPrompts.length) {
this.promptWrapper.style.display = "block";
} else {
this.promptWrapper.style.display = "none";
}
};
/*
Adds a new password prompt. Options are:
submitText: text to use for submit button (defaults to "Login")
serviceName: text of the human readable service name
noUserName: set true to disable username prompt
canCancel: set true to enable a cancel button (callback called with null)
repeatPassword: set true to prompt for the password twice
callback: function to be called on submission with parameter of object {username:,password:}. Callback must return `true` to remove the password prompt
*/
$tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
// Create and add the prompt to the DOM
var self = this,
submitText = options.submitText || "Login",
dm = $tw.utils.domMaker,
children = [dm("h1",{text: options.serviceName})];
if(!options.noUserName) {
children.push(dm("input",{
attributes: {type: "text", name: "username", placeholder: $tw.language.getString("Encryption/Username")}
}));
}
children.push(dm("input",{
attributes: {
type: "password",
name: "password",
placeholder: ( $tw.language == undefined ? "Password" : $tw.language.getString("Encryption/Password") )
}
}));
if(options.repeatPassword) {
children.push(dm("input",{
attributes: {
type: "password",
name: "password2",
placeholder: $tw.language.getString("Encryption/RepeatPassword")
}
}));
}
if(options.canCancel) {
children.push(dm("button",{
text: $tw.language.getString("Encryption/Cancel"),
attributes: {
type: "button"
},
eventListeners: [{
name: "click",
handlerFunction: function(event) {
self.removePrompt(promptInfo);
options.callback(null);
}
}]
}));
}
children.push(dm("button",{
attributes: {type: "submit"},
text: submitText
}));
var form = dm("form",{
attributes: {autocomplete: "off"},
children: children
});
this.promptWrapper.appendChild(form);
window.setTimeout(function() {
form.elements[0].focus();
},10);
// Add a submit event handler
var self = this;
form.addEventListener("submit",function(event) {
// Collect the form data
var data = {},t;
$tw.utils.each(form.elements,function(element) {
if(element.name && element.value) {
data[element.name] = element.value;
}
});
// Check that the passwords match
if(options.repeatPassword && data.password !== data.password2) {
alert($tw.language.getString("Encryption/PasswordNoMatch"));
} else {
// Call the callback
if(options.callback(data)) {
// Remove the prompt if the callback returned true
self.removePrompt(promptInfo);
} else {
// Clear the password if the callback returned false
$tw.utils.each(form.elements,function(element) {
if(element.name === "password" || element.name === "password2") {
element.value = "";
}
});
}
}
event.preventDefault();
return false;
},true);
// Add the prompt to the list
var promptInfo = {
serviceName: options.serviceName,
callback: options.callback,
2022-04-14 23:41:27 +00:00
form: form,
owner: this
};
this.passwordPrompts.push(promptInfo);
// Make sure the wrapper is displayed
this.setWrapperDisplay();
2022-04-14 23:41:27 +00:00
return promptInfo;
};
$tw.utils.PasswordPrompt.prototype.removePrompt = function(promptInfo) {
var i = this.passwordPrompts.indexOf(promptInfo);
if(i !== -1) {
this.passwordPrompts.splice(i,1);
promptInfo.form.parentNode.removeChild(promptInfo.form);
this.setWrapperDisplay();
}
}
/*
Crypto helper object for encrypted content. It maintains the password text in a closure, and provides methods to change
the password, and to encrypt/decrypt a block of text
*/
$tw.utils.Crypto = function() {
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
currentPassword = null,
callSjcl = function(method,inputText,password) {
password = password || currentPassword;
var outputText;
try {
if(password) {
outputText = sjcl[method](password,inputText);
}
} catch(ex) {
console.log("Crypto error:" + ex);
outputText = null;
}
return outputText;
};
this.setPassword = function(newPassword) {
currentPassword = newPassword;
this.updateCryptoStateTiddler();
};
this.updateCryptoStateTiddler = function() {
if($tw.wiki) {
var state = currentPassword ? "yes" : "no",
tiddler = $tw.wiki.getTiddler("$:/isEncrypted");
if(!tiddler || tiddler.fields.text !== state) {
$tw.wiki.addTiddler(new $tw.Tiddler({title: "$:/isEncrypted", text: state}));
}
}
};
this.hasPassword = function() {
return !!currentPassword;
}
this.encrypt = function(text,password) {
return callSjcl("encrypt",text,password);
};
this.decrypt = function(text,password) {
return callSjcl("decrypt",text,password);
};
};
/////////////////////////// Module mechanism
/*
Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot'
*/
$tw.modules.execute = function(moduleName,moduleRoot) {
var name = moduleName;
if(moduleName.charAt(0) === ".") {
name = $tw.utils.resolvePath(moduleName,moduleRoot)
}
if(!$tw.modules.titles[name]) {
if($tw.modules.titles[name + ".js"]) {
name = name + ".js";
} else if($tw.modules.titles[name + "/index.js"]) {
name = name + "/index.js";
} else if($tw.modules.titles[moduleName]) {
name = moduleName;
} else if($tw.modules.titles[moduleName + ".js"]) {
name = moduleName + ".js";
} else if($tw.modules.titles[moduleName + "/index.js"]) {
name = moduleName + "/index.js";
}
}
var moduleInfo = $tw.modules.titles[name],
tiddler = $tw.wiki.getTiddler(name),
_exports = {},
sandbox = {
module: {exports: _exports},
//moduleInfo: moduleInfo,
exports: _exports,
console: console,
setInterval: setInterval,
clearInterval: clearInterval,
setTimeout: setTimeout,
clearTimeout: clearTimeout,
Buffer: $tw.browser ? undefined : Buffer,
$tw: $tw,
require: function(title) {
return $tw.modules.execute(title, name);
}
};
Object.defineProperty(sandbox.module, "id", {
value: name,
writable: false,
enumerable: true,
configurable: false
});
if(!$tw.browser) {
$tw.utils.extend(sandbox,{
process: process
});
} else {
/*
CommonJS optional require.main property:
In a browser we offer a fake main module which points back to the boot function
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
*/
Object.defineProperty(sandbox.require, "main", {
value: (typeof(require) !== "undefined") ? require.main : {TiddlyWiki: _boot},
writable: false,
enumerable: true,
configurable: false
});
}
if(!moduleInfo) {
// We could not find the module on this path
// Try to defer to browserify etc, or node
var deferredModule;
if($tw.browser) {
if(window.require) {
try {
return window.require(moduleName);
} catch(e) {}
}
throw "Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name;
} else {
// If we don't have a module with that name, let node.js try to find it
return require(moduleName);
}
}
// Execute the module if we haven't already done so
if(!moduleInfo.exports) {
try {
// Check the type of the definition
if(typeof moduleInfo.definition === "function") { // Function
moduleInfo.exports = _exports;
moduleInfo.definition(moduleInfo,moduleInfo.exports,sandbox.require);
} else if(typeof moduleInfo.definition === "string") { // String
moduleInfo.exports = _exports;
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
if(sandbox.module.exports) {
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
}
} else { // Object
moduleInfo.exports = moduleInfo.definition;
}
} catch(e) {
if (e instanceof SyntaxError) {
var line = e.lineNumber || e.line; // Firefox || Safari
if (typeof(line) != "undefined" && line !== null) {
$tw.utils.error("Syntax error in boot module " + name + ":" + line + ":\n" + e.stack);
} else if(!$tw.browser) {
// this is the only way to get node.js to display the line at which the syntax error appeared,
// and $tw.utils.error would exit anyway
// cf. https://bugs.chromium.org/p/v8/issues/detail?id=2589
throw e;
} else {
// Opera: line number is included in e.message
// Chrome/IE: there's currently no way to get the line number
$tw.utils.error("Syntax error in boot module " + name + ": " + e.message + "\n" + e.stack);
}
} else {
// line number should be included in e.stack for runtime errors
$tw.utils.error("Error executing boot module " + name + ": " + JSON.stringify(e) + "\n\n" + e.stack);
}
}
}
// Return the exports of the module
return moduleInfo.exports;
};
/*
Apply a callback to each module of a particular type
moduleType: type of modules to enumerate
callback: function called as callback(title,moduleExports) for each module
*/
$tw.modules.forEachModuleOfType = function(moduleType,callback) {
var modules = $tw.modules.types[moduleType];
$tw.utils.each(modules,function(element,title) {
callback(title,$tw.modules.execute(title));
});
};
/*
Get all the modules of a particular type in a hashmap by their `name` field
*/
$tw.modules.getModulesByTypeAsHashmap = function(moduleType,nameField) {
nameField = nameField || "name";
var results = Object.create(null);
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
results[module[nameField]] = module;
});
return results;
};
/*
Apply the exports of the modules of a particular type to a target object
*/
$tw.modules.applyMethods = function(moduleType,targetObject) {
if(!targetObject) {
targetObject = Object.create(null);
}
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
$tw.utils.each(module,function(element,title,object) {
targetObject[title] = module[title];
});
});
return targetObject;
};
2022-04-14 23:41:27 +00:00
/*
Return a class created from a modules. The module should export the properties to be added to those of the optional base class
*/
$tw.modules.createClassFromModule = function(moduleExports,baseClass) {
var newClass = function() {};
if(baseClass) {
newClass.prototype = new baseClass();
newClass.prototype.constructor = baseClass;
}
$tw.utils.extend(newClass.prototype,moduleExports);
return newClass;
};
/*
Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class
*/
$tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
var classes = Object.create(null);
$tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) {
if(!subType || moduleExports.types[subType]) {
2022-04-14 23:41:27 +00:00
classes[moduleExports.name] = $tw.modules.createClassFromModule(moduleExports,baseClass);
}
});
return classes;
};
/////////////////////////// Barebones tiddler object
/*
Construct a tiddler object from a hashmap of tiddler fields. If multiple hasmaps are provided they are merged,
taking precedence to the right
*/
$tw.Tiddler = function(/* [fields,] fields */) {
this.fields = Object.create(null);
this.cache = Object.create(null);
for(var c=0; c<arguments.length; c++) {
var arg = arguments[c],
src = (arg instanceof $tw.Tiddler) ? arg.fields : arg;
for(var t in src) {
if(src[t] === undefined || src[t] === null) {
if(t in this.fields) {
delete this.fields[t]; // If we get a field that's undefined, delete any previous field value
}
} else {
// Parse the field with the associated field module (if any)
var fieldModule = $tw.Tiddler.fieldModules[t],
value;
if(fieldModule && fieldModule.parse) {
value = fieldModule.parse.call(this,src[t]);
} else {
value = src[t];
}
// Freeze the field to keep it immutable
if(value != null && typeof value === "object") {
Object.freeze(value);
}
this.fields[t] = value;
}
}
}
// Freeze the tiddler against modification
Object.freeze(this.fields);
Object.freeze(this);
};
$tw.Tiddler.prototype.hasField = function(field) {
return $tw.utils.hop(this.fields,field);
};
/*
Compare two tiddlers for equality
tiddler: the tiddler to compare
excludeFields: array of field names to exclude from the comparison
*/
$tw.Tiddler.prototype.isEqual = function(tiddler,excludeFields) {
if(!(tiddler instanceof $tw.Tiddler)) {
return false;
}
excludeFields = excludeFields || [];
var self = this,
differences = []; // Fields that have differences
// Add to the differences array
function addDifference(fieldName) {
// Check for this field being excluded
if(excludeFields.indexOf(fieldName) === -1) {
// Save the field as a difference
$tw.utils.pushTop(differences,fieldName);
}
}
// Returns true if the two values of this field are equal
function isFieldValueEqual(fieldName) {
var valueA = self.fields[fieldName],
valueB = tiddler.fields[fieldName];
// Check for identical string values
if(typeof(valueA) === "string" && typeof(valueB) === "string" && valueA === valueB) {
return true;
}
// Check for identical array values
if($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {
return true;
}
// Check for identical date values
if($tw.utils.isDate(valueA) && $tw.utils.isDate(valueB) && valueA.getTime() === valueB.getTime()) {
return true;
}
// Otherwise the fields must be different
return false;
}
// Compare our fields
for(var fieldName in this.fields) {
if(!isFieldValueEqual(fieldName)) {
addDifference(fieldName);
}
}
// There's a difference for every field in the other tiddler that we don't have
for(fieldName in tiddler.fields) {
if(!(fieldName in this.fields)) {
addDifference(fieldName);
}
}
// Return whether there were any differences
return differences.length === 0;
};
/*
Register and install the built in tiddler field modules
*/
$tw.modules.define("$:/boot/tiddlerfields/modified","tiddlerfield",{
name: "modified",
parse: $tw.utils.parseDate,
stringify: $tw.utils.stringifyDate
});
$tw.modules.define("$:/boot/tiddlerfields/created","tiddlerfield",{
name: "created",
parse: $tw.utils.parseDate,
stringify: $tw.utils.stringifyDate
});
$tw.modules.define("$:/boot/tiddlerfields/color","tiddlerfield",{
name: "color",
editTag: "input",
editType: "color"
});
$tw.modules.define("$:/boot/tiddlerfields/tags","tiddlerfield",{
name: "tags",
parse: $tw.utils.parseStringArray,
stringify: $tw.utils.stringifyList
});
$tw.modules.define("$:/boot/tiddlerfields/list","tiddlerfield",{
name: "list",
parse: $tw.utils.parseStringArray,
stringify: $tw.utils.stringifyList
});
/////////////////////////// Barebones wiki store
/*
Wiki constructor. State is stored in private members that only a small number of privileged accessor methods have direct access. Methods added via the prototype have to use these accessors and cannot access the state data directly.
options include:
enableIndexers - Array of indexer names to enable, or null to use all available indexers
*/
$tw.Wiki = function(options) {
options = options || {};
var self = this,
tiddlers = Object.create(null), // Hashmap of tiddlers
tiddlerTitles = null, // Array of tiddler titles
getTiddlerTitles = function() {
if(!tiddlerTitles) {
2022-04-14 23:41:27 +00:00
tiddlerTitles = Object.keys(tiddlers).sort(function(a,b) {return a.localeCompare(b);});
}
return tiddlerTitles;
},
pluginTiddlers = [], // Array of tiddlers containing registered plugins, ordered by priority
pluginInfo = Object.create(null), // Hashmap of parsed plugin content
shadowTiddlers = Object.create(null), // Hashmap by title of {source:, tiddler:}
shadowTiddlerTitles = null,
getShadowTiddlerTitles = function() {
if(!shadowTiddlerTitles) {
shadowTiddlerTitles = Object.keys(shadowTiddlers);
}
return shadowTiddlerTitles;
},
enableIndexers = options.enableIndexers || null,
indexers = [],
indexersByName = Object.create(null);
this.addIndexer = function(indexer,name) {
// Bail if this indexer is not enabled
if(enableIndexers && enableIndexers.indexOf(name) === -1) {
return;
}
indexers.push(indexer);
indexersByName[name] = indexer;
indexer.init();
};
this.getIndexer = function(name) {
return indexersByName[name] || null;
};
// Add a tiddler to the store
this.addTiddler = function(tiddler) {
if(!(tiddler instanceof $tw.Tiddler)) {
tiddler = new $tw.Tiddler(tiddler);
}
// Save the tiddler
if(tiddler) {
var title = tiddler.fields.title;
if(title) {
// Uncomment the following line for detailed logs of all tiddler writes
// console.log("Adding",title,tiddler)
// Record the old tiddler state
var updateDescriptor = {
old: {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
// Save the new tiddler
tiddlers[title] = tiddler;
2022-04-14 23:41:27 +00:00
// Check we've got the title
tiddlerTitles = $tw.utils.insertSortedArray(tiddlerTitles || [],title);
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: tiddler,
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.update(updateDescriptor);
});
// Queue a change event
this.enqueueTiddlerEvent(title);
}
}
};
// Delete a tiddler
this.deleteTiddler = function(title) {
// Uncomment the following line for detailed logs of all tiddler deletions
// console.log("Deleting",title)
if($tw.utils.hop(tiddlers,title)) {
// Record the old tiddler state
var updateDescriptor = {
old: {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
// Delete the tiddler
delete tiddlers[title];
// Delete it from the list of titles
if(tiddlerTitles) {
var index = tiddlerTitles.indexOf(title);
if(index !== -1) {
tiddlerTitles.splice(index,1);
2022-04-14 23:41:27 +00:00
}
}
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.update(updateDescriptor);
});
// Queue a change event
this.enqueueTiddlerEvent(title,true);
}
};
// Get a tiddler from the store
this.getTiddler = function(title) {
if(title) {
var t = tiddlers[title];
if(t instanceof $tw.Tiddler) {
return t;
} else if(title !== undefined && shadowTiddlers[title]) {
return shadowTiddlers[title].tiddler;
}
return undefined;
}
};
// Get an array of all tiddler titles
this.allTitles = function() {
return getTiddlerTitles().slice(0);
};
// Iterate through all tiddler titles
this.each = function(callback) {
var titles = getTiddlerTitles(),
index,titlesLength,title;
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
callback(tiddlers[title],title);
}
};
// Get an array of all shadow tiddler titles
this.allShadowTitles = function() {
return getShadowTiddlerTitles().slice(0);
};
// Iterate through all shadow tiddler titles
this.eachShadow = function(callback) {
var titles = getShadowTiddlerTitles(),
index,titlesLength,title;
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
2022-04-14 23:41:27 +00:00
if(tiddlers[title]) {
callback(tiddlers[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
}
};
// Iterate through all tiddlers and then the shadows
this.eachTiddlerPlusShadows = function(callback) {
var index,titlesLength,title,
titles = getTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
callback(tiddlers[title],title);
}
titles = getShadowTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(!tiddlers[title]) {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
}
};
// Iterate through all the shadows and then the tiddlers
this.eachShadowPlusTiddlers = function(callback) {
var index,titlesLength,title,
titles = getShadowTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(tiddlers[title]) {
callback(tiddlers[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
}
titles = getTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(!shadowTiddlers[title]) {
callback(tiddlers[title],title);
}
}
};
// Test for the existence of a tiddler (excludes shadow tiddlers)
this.tiddlerExists = function(title) {
return !!$tw.utils.hop(tiddlers,title);
};
// Determines if a tiddler is a shadow tiddler, regardless of whether it has been overridden by a real tiddler
this.isShadowTiddler = function(title) {
return $tw.utils.hop(shadowTiddlers,title);
};
this.getShadowSource = function(title) {
if($tw.utils.hop(shadowTiddlers,title)) {
return shadowTiddlers[title].source;
}
return null;
};
2022-04-14 23:41:27 +00:00
// Get an array of all the currently recognised plugin types
this.getPluginTypes = function() {
var types = [];
$tw.utils.each(pluginTiddlers,function(pluginTiddler) {
var pluginType = pluginTiddler.fields["plugin-type"];
if(pluginType && types.indexOf(pluginType) === -1) {
types.push(pluginType);
}
2022-04-14 23:41:27 +00:00
});
return types;
};
2022-04-14 23:41:27 +00:00
// Read plugin info for all plugins, or just an array of titles. Returns the number of plugins updated or deleted
this.readPluginInfo = function(titles) {
var results = {
modifiedPlugins: [],
deletedPlugins: []
};
$tw.utils.each(titles || getTiddlerTitles(),function(title) {
var tiddler = tiddlers[title];
if(tiddler) {
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type") && tiddler.fields.text) {
pluginInfo[tiddler.fields.title] = $tw.utils.parseJSONSafe(tiddler.fields.text);
results.modifiedPlugins.push(tiddler.fields.title);
}
} else {
if(pluginInfo[title]) {
delete pluginInfo[title];
results.deletedPlugins.push(title);
}
}
});
return results;
};
// Get plugin info for a plugin
this.getPluginInfo = function(title) {
return pluginInfo[title];
};
2022-04-14 23:41:27 +00:00
// Register the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting registration to an array of tiddler titles. Return the array of titles affected
this.registerPluginTiddlers = function(pluginType,titles) {
var self = this,
registeredTitles = [],
checkTiddler = function(tiddler,title) {
2022-04-14 23:41:27 +00:00
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
2022-04-14 23:41:27 +00:00
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
pluginTiddlers.push(tiddler);
registeredTitles.push(tiddler.fields.title);
}
}
};
if(titles) {
$tw.utils.each(titles,function(title) {
checkTiddler(self.getTiddler(title),title);
});
} else {
this.each(function(tiddler,title) {
checkTiddler(tiddler,title);
});
}
return registeredTitles;
};
2022-04-14 23:41:27 +00:00
// Unregister the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting unregistering to an array of tiddler titles. Returns an array of the titles affected
this.unregisterPluginTiddlers = function(pluginType,titles) {
var self = this,
2022-04-14 23:41:27 +00:00
unregisteredTitles = [];
// Remove any previous registered plugins of this type
for(var t=pluginTiddlers.length-1; t>=0; t--) {
var tiddler = pluginTiddlers[t];
2022-04-14 23:41:27 +00:00
if(tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType) && (!titles || titles.indexOf(tiddler.fields.title) !== -1)) {
unregisteredTitles.push(tiddler.fields.title);
pluginTiddlers.splice(t,1);
}
}
2022-04-14 23:41:27 +00:00
return unregisteredTitles;
};
// Unpack the currently registered plugins, creating shadow tiddlers for their constituent tiddlers
this.unpackPluginTiddlers = function() {
var self = this;
// Sort the plugin titles by the `plugin-priority` field
pluginTiddlers.sort(function(a,b) {
if("plugin-priority" in a.fields && "plugin-priority" in b.fields) {
return a.fields["plugin-priority"] - b.fields["plugin-priority"];
} else if("plugin-priority" in a.fields) {
return -1;
} else if("plugin-priority" in b.fields) {
return +1;
} else if(a.fields.title < b.fields.title) {
return -1;
} else if(a.fields.title === b.fields.title) {
return 0;
} else {
return +1;
}
});
// Now go through the plugins in ascending order and assign the shadows
shadowTiddlers = Object.create(null);
$tw.utils.each(pluginTiddlers,function(tiddler) {
// Extract the constituent tiddlers
if($tw.utils.hop(pluginInfo,tiddler.fields.title)) {
$tw.utils.each(pluginInfo[tiddler.fields.title].tiddlers,function(constituentTiddler,constituentTitle) {
// Save the tiddler object
if(constituentTitle) {
shadowTiddlers[constituentTitle] = {
source: tiddler.fields.title,
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
};
}
});
}
});
shadowTiddlerTitles = null;
this.clearCache(null);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.rebuild();
});
};
if(this.addIndexersToWiki) {
this.addIndexersToWiki();
}
};
// Dummy methods that will be filled in after boot
$tw.Wiki.prototype.clearCache =
$tw.Wiki.prototype.clearGlobalCache =
$tw.Wiki.prototype.enqueueTiddlerEvent = function() {};
// Add an array of tiddlers
$tw.Wiki.prototype.addTiddlers = function(tiddlers) {
for(var t=0; t<tiddlers.length; t++) {
this.addTiddler(tiddlers[t]);
}
};
/*
Define all modules stored in ordinary tiddlers
*/
$tw.Wiki.prototype.defineTiddlerModules = function() {
this.each(function(tiddler,title) {
if(tiddler.hasField("module-type")) {
switch (tiddler.fields.type) {
case "application/javascript":
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
if(!$tw.utils.hop($tw.modules.titles,tiddler.fields.title)) {
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
}
break;
case "application/json":
2022-04-14 23:41:27 +00:00
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseJSONSafe(tiddler.fields.text));
break;
case "application/x-tiddler-dictionary":
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseFields(tiddler.fields.text));
break;
}
}
});
};
/*
Register all the module tiddlers that have a module type
*/
$tw.Wiki.prototype.defineShadowModules = function() {
var self = this;
this.eachShadow(function(tiddler,title) {
// Don't define the module if it is overidden by an ordinary tiddler
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
// Define the module
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
}
});
};
/*
Enable safe mode by deleting any tiddlers that override a shadow tiddler
*/
$tw.Wiki.prototype.processSafeMode = function() {
var self = this,
overrides = [];
// Find the overriding tiddlers
this.each(function(tiddler,title) {
if(self.isShadowTiddler(title)) {
console.log(title);
overrides.push(title);
}
});
// Assemble a report tiddler
var titleReportTiddler = "TiddlyWiki Safe Mode",
report = [];
report.push("TiddlyWiki has been started in [[safe mode|https://tiddlywiki.com/static/SafeMode.html]]. All plugins are temporarily disabled. Most customisations have been disabled by renaming the following tiddlers:")
// Delete the overrides
overrides.forEach(function(title) {
var tiddler = self.getTiddler(title),
newTitle = "SAFE: " + title;
self.deleteTiddler(title);
self.addTiddler(new $tw.Tiddler(tiddler, {title: newTitle}));
report.push("* [[" + title + "|" + newTitle + "]]");
});
report.push()
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
// Set $:/DefaultTiddlers to point to our report
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
};
/*
Extracts tiddlers from a typed block of text, specifying default field values
*/
$tw.Wiki.prototype.deserializeTiddlers = function(type,text,srcFields,options) {
srcFields = srcFields || Object.create(null);
options = options || {};
var deserializer = $tw.Wiki.tiddlerDeserializerModules[options.deserializer],
fields = Object.create(null);
if(!deserializer) {
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
}
if(!deserializer && $tw.utils.getFileExtensionInfo(type)) {
// If we didn't find the serializer, try converting it from an extension to a content type
type = $tw.utils.getFileExtensionInfo(type).type;
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
}
if(!deserializer && $tw.config.contentTypeInfo[type]) {
// see if this type has a different deserializer registered with it
type = $tw.config.contentTypeInfo[type].deserializerType;
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
}
if(!deserializer) {
// If we still don't have a deserializer, treat it as plain text
deserializer = $tw.Wiki.tiddlerDeserializerModules["text/plain"];
}
for(var f in srcFields) {
fields[f] = srcFields[f];
}
if(deserializer) {
return deserializer.call(this,text,fields,type);
} else {
// Return a raw tiddler for unknown types
fields.text = text;
return [fields];
}
};
/*
Register the built in tiddler deserializer modules
*/
var deserializeHeaderComment = function(text,fields) {
var headerCommentRegExp = new RegExp($tw.config.jsModuleHeaderRegExpString,"mg"),
match = headerCommentRegExp.exec(text);
fields.text = text;
if(match) {
fields = $tw.utils.parseFields(match[1].split(/\r?\n\r?\n/mg)[0],fields);
}
return [fields];
};
$tw.modules.define("$:/boot/tiddlerdeserializer/js","tiddlerdeserializer",{
"application/javascript": deserializeHeaderComment
});
$tw.modules.define("$:/boot/tiddlerdeserializer/css","tiddlerdeserializer",{
"text/css": deserializeHeaderComment
});
$tw.modules.define("$:/boot/tiddlerdeserializer/tid","tiddlerdeserializer",{
"application/x-tiddler": function(text,fields) {
var split = text.split(/\r?\n\r?\n/mg);
if(split.length >= 1) {
fields = $tw.utils.parseFields(split[0],fields);
}
if(split.length >= 2) {
fields.text = split.slice(1).join("\n\n");
}
return [fields];
}
});
$tw.modules.define("$:/boot/tiddlerdeserializer/tids","tiddlerdeserializer",{
"application/x-tiddlers": function(text,fields) {
var titles = [],
tiddlers = [],
match = /\r?\n\r?\n/mg.exec(text);
if(match) {
fields = $tw.utils.parseFields(text.substr(0,match.index),fields);
var lines = text.substr(match.index + match[0].length).split(/\r?\n/mg);
for(var t=0; t<lines.length; t++) {
var line = lines[t];
if(line.charAt(0) !== "#") {
var colonPos= line.indexOf(":");
if(colonPos !== -1) {
var tiddler = $tw.utils.extend(Object.create(null),fields);
tiddler.title = (tiddler.title || "") + line.substr(0,colonPos).trim();
if(titles.indexOf(tiddler.title) !== -1) {
console.log("Warning: .multids file contains multiple definitions for " + tiddler.title);
}
titles.push(tiddler.title);
tiddler.text = line.substr(colonPos + 2).trim();
tiddlers.push(tiddler);
}
}
}
}
return tiddlers;
}
});
$tw.modules.define("$:/boot/tiddlerdeserializer/txt","tiddlerdeserializer",{
"text/plain": function(text,fields,type) {
fields.text = text;
fields.type = type || "text/plain";
return [fields];
}
});
$tw.modules.define("$:/boot/tiddlerdeserializer/html","tiddlerdeserializer",{
"text/html": function(text,fields) {
fields.text = text;
fields.type = "text/html";
return [fields];
}
});
$tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
"application/json": function(text,fields) {
var isTiddlerValid = function(data) {
// Not valid if it's not an object with a title property
if(typeof(data) !== "object" || !$tw.utils.hop(data,"title")) {
return false;
}
for(var f in data) {
if($tw.utils.hop(data,f)) {
2022-04-14 23:41:27 +00:00
// Check field name doesn't contain control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F]/.test(f)) {
return false;
}
}
}
return true;
},
isTiddlerArrayValid = function(data) {
for(var t=0; t<data.length; t++) {
if(!isTiddlerValid(data[t])) {
return false;
}
}
return true;
},
2022-04-14 23:41:27 +00:00
data = $tw.utils.parseJSONSafe(text);
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
return data;
} else if(isTiddlerValid(data)) {
return [data];
} else {
// Plain JSON file
fields.text = text;
fields.type = "application/json";
return [fields];
}
}
});
/////////////////////////// Browser definitions
if($tw.browser && !$tw.node) {
/*
Decrypt any tiddlers stored within the element with the ID "encryptedArea". The function is asynchronous to allow the user to be prompted for a password
callback: function to be called the decryption is complete
*/
$tw.boot.decryptEncryptedTiddlers = function(callback) {
var encryptedArea = document.getElementById("encryptedStoreArea");
if(encryptedArea) {
var encryptedText = encryptedArea.innerHTML,
prompt = "Enter a password to decrypt this TiddlyWiki";
// Prompt for the password
if($tw.utils.hop($tw.boot,"encryptionPrompts")) {
prompt = $tw.boot.encryptionPrompts.decrypt;
}
$tw.passwordPrompt.createPrompt({
serviceName: prompt,
noUserName: true,
submitText: "Decrypt",
callback: function(data) {
// Attempt to decrypt the tiddlers
$tw.crypto.setPassword(data.password);
var decryptedText = $tw.crypto.decrypt(encryptedText);
if(decryptedText) {
2022-04-14 23:41:27 +00:00
var json = $tw.utils.parseJSONSafe(decryptedText);
for(var title in json) {
$tw.preloadTiddler(json[title]);
}
// Call the callback
callback();
// Exit and remove the password prompt
return true;
} else {
// We didn't decrypt everything, so continue to prompt for password
return false;
}
}
});
} else {
// Just invoke the callback straight away if there weren't any encrypted tiddlers
callback();
}
};
/*
Register a deserializer that can extract tiddlers from the DOM
*/
$tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
"(DOM)": function(node) {
var extractTextTiddlers = function(node) {
var e = node.firstChild;
while(e && e.nodeName.toLowerCase() !== "pre") {
e = e.nextSibling;
}
var title = node.getAttribute ? node.getAttribute("title") : null;
if(e && title) {
var attrs = node.attributes,
tiddler = {
text: $tw.utils.htmlDecode(e.innerHTML)
};
for(var i=attrs.length-1; i >= 0; i--) {
tiddler[attrs[i].name] = attrs[i].value;
}
return [tiddler];
} else {
return null;
}
},
extractModuleTiddlers = function(node) {
if(node.hasAttribute && node.hasAttribute("data-tiddler-title")) {
var text = node.innerHTML,
s = text.indexOf("{"),
e = text.lastIndexOf("}");
if(node.hasAttribute("data-module") && s !== -1 && e !== -1) {
text = text.substring(s+1,e);
}
var fields = {text: text},
attributes = node.attributes;
for(var a=0; a<attributes.length; a++) {
if(attributes[a].nodeName.substr(0,13) === "data-tiddler-") {
fields[attributes[a].nodeName.substr(13)] = attributes[a].value;
}
}
return [fields];
} else {
return null;
}
},
t,result = [];
if(node) {
2022-04-14 23:41:27 +00:00
var type = (node.getAttribute && node.getAttribute("type")) || null;
if(type) {
// A new-style container with an explicit deserialization type
result = $tw.wiki.deserializeTiddlers(type,node.textContent);
} else {
// An old-style container of classic DIV-based tiddlers
for(t = 0; t < node.childNodes.length; t++) {
var childNode = node.childNodes[t],
tiddlers = extractTextTiddlers(childNode);
tiddlers = tiddlers || extractModuleTiddlers(childNode);
if(tiddlers) {
result.push.apply(result,tiddlers);
}
2022-04-14 23:41:27 +00:00
}
}
}
return result;
}
});
$tw.loadTiddlersBrowser = function() {
// In the browser, we load tiddlers from certain elements
2022-04-14 23:41:27 +00:00
var containerSelectors = [
// IDs for old-style v5.1.x tiddler stores
"#libraryModules",
"#modules",
"#bootKernelPrefix",
"#bootKernel",
"#styleArea",
"#storeArea",
"#systemArea",
// Classes for new-style v5.2.x JSON tiddler stores
"script.tiddlywiki-tiddler-store"
];
2022-04-14 23:41:27 +00:00
for(var t=0; t<containerSelectors.length; t++) {
var nodes = document.querySelectorAll(containerSelectors[t]);
for(var n=0; n<nodes.length; n++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",nodes[n]));
}
}
};
} else {
/////////////////////////// Server definitions
/*
Get any encrypted tiddlers
*/
$tw.boot.decryptEncryptedTiddlers = function(callback) {
// Storing encrypted tiddlers on the server isn't supported yet
callback();
};
} // End of if($tw.browser && !$tw.node)
/////////////////////////// Node definitions
if($tw.node) {
/*
Load the tiddlers contained in a particular file (and optionally extract fields from the accompanying .meta file) returned as {filepath:,type:,tiddlers:[],hasMetaFile:}
*/
$tw.loadTiddlersFromFile = function(filepath,fields) {
var ext = path.extname(filepath),
extensionInfo = $tw.utils.getFileExtensionInfo(ext),
type = extensionInfo ? extensionInfo.type : null,
typeInfo = type ? $tw.config.contentTypeInfo[type] : null,
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8"),
tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
metadata = $tw.loadMetadataForFile(filepath);
if(metadata) {
if(type === "application/json") {
tiddlers = [{text: data, type: "application/json"}];
}
tiddlers = [$tw.utils.extend({},tiddlers[0],metadata)];
}
return {filepath: filepath, type: type, tiddlers: tiddlers, hasMetaFile: !!metadata};
};
/*
Load the metadata fields in the .meta file corresponding to a particular file
*/
$tw.loadMetadataForFile = function(filepath) {
var metafilename = filepath + ".meta";
if(fs.existsSync(metafilename)) {
return $tw.utils.parseFields(fs.readFileSync(metafilename,"utf8") || "");
} else {
return null;
}
};
/*
A default set of files for TiddlyWiki to ignore during load.
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
metadata files.
*/
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
/*
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
*/
$tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
var tiddlers = [];
if(fs.existsSync(filepath)) {
var stat = fs.statSync(filepath);
if(stat.isDirectory()) {
var files = fs.readdirSync(filepath);
// Look for a tiddlywiki.files file
if(files.indexOf("tiddlywiki.files") !== -1) {
Array.prototype.push.apply(tiddlers,$tw.loadTiddlersFromSpecification(filepath,excludeRegExp));
} else {
// If not, read all the files in the directory
$tw.utils.each(files,function(file) {
if(!excludeRegExp.test(file) && file !== "plugin.info") {
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(filepath + path.sep + file,excludeRegExp));
}
});
}
} else if(stat.isFile()) {
tiddlers.push($tw.loadTiddlersFromFile(filepath,{title: filepath}));
}
}
return tiddlers;
};
/*
Load all the tiddlers defined by a `tiddlywiki.files` specification file
filepath: pathname of the directory containing the specification file
*/
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var tiddlers = [];
// Read the specification
2022-04-14 23:41:27 +00:00
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
2022-04-14 23:41:27 +00:00
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
type = (extInfo || {}).type || fields.type || "text/plain",
typeInfo = $tw.config.contentTypeInfo[type] || {},
pathname = path.resolve(filepath,filename),
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8"),
metadata = $tw.loadMetadataForFile(pathname) || {},
fileTiddlers;
if(isTiddlerFile) {
fileTiddlers = $tw.wiki.deserializeTiddlers(path.extname(pathname),text,metadata) || [];
} else {
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
}
var combinedFields = $tw.utils.extend({},fields,metadata);
$tw.utils.each(fileTiddlers,function(tiddler) {
$tw.utils.each(combinedFields,function(fieldInfo,name) {
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
tiddler[name] = fieldInfo;
} else {
var value = tiddler[name];
switch(fieldInfo.source) {
case "filename":
value = path.basename(filename);
break;
case "filename-uri-decoded":
2022-04-14 23:41:27 +00:00
value = $tw.utils.decodeURIComponentSafe(path.basename(filename));
break;
case "basename":
value = path.basename(filename,path.extname(filename));
break;
case "basename-uri-decoded":
2022-04-14 23:41:27 +00:00
value = $tw.utils.decodeURIComponentSafe(path.basename(filename,path.extname(filename)));
break;
case "extname":
value = path.extname(filename);
break;
case "created":
value = new Date(fs.statSync(pathname).birthtime);
break;
case "modified":
value = new Date(fs.statSync(pathname).mtime);
break;
}
if(fieldInfo.prefix) {
value = fieldInfo.prefix + value;
}
if(fieldInfo.suffix) {
value = value + fieldInfo.suffix;
}
tiddler[name] = value;
}
});
});
2022-04-14 23:41:27 +00:00
if(isEditableFile) {
tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, isEditableFile: true, tiddlers: fileTiddlers});
} else {
tiddlers.push({tiddlers: fileTiddlers});
}
};
2022-04-14 23:41:27 +00:00
// Helper to recursively search subdirectories
var getAllFiles = function(dirPath, recurse, arrayOfFiles) {
recurse = recurse || false;
arrayOfFiles = arrayOfFiles || [];
var files = fs.readdirSync(dirPath);
files.forEach(function(file) {
if (recurse && fs.statSync(dirPath + path.sep + file).isDirectory()) {
arrayOfFiles = getAllFiles(dirPath + path.sep + file, recurse, arrayOfFiles);
} else if(fs.statSync(dirPath + path.sep + file).isFile()){
arrayOfFiles.push(path.join(dirPath, path.sep, file));
}
});
return arrayOfFiles;
}
// Process the listed tiddlers
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
if(tidInfo.prefix && tidInfo.suffix) {
tidInfo.fields.text = {prefix: tidInfo.prefix,suffix: tidInfo.suffix};
} else if(tidInfo.prefix) {
tidInfo.fields.text = {prefix: tidInfo.prefix};
} else if(tidInfo.suffix) {
tidInfo.fields.text = {suffix: tidInfo.suffix};
}
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
});
// Process any listed directories
$tw.utils.each(filesInfo.directories,function(dirSpec) {
// Read literal directories directly
if(typeof dirSpec === "string") {
var pathname = path.resolve(filepath,dirSpec);
if(fs.existsSync(pathname) && fs.statSync(pathname).isDirectory()) {
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(pathname,excludeRegExp));
}
} else {
// Process directory specifier
2022-04-14 23:41:27 +00:00
var dirPath = path.resolve(filepath,dirSpec.path);
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
var files = getAllFiles(dirPath, dirSpec.searchSubdirectories),
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
metaRegExp = /^.*\.meta$/;
for(var t=0; t<files.length; t++) {
var thisPath = path.relative(filepath, files[t]),
filename = path.basename(thisPath);
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
}
}
2022-04-14 23:41:27 +00:00
} else {
console.log("Warning: a directory in a tiddlywiki.files file does not exist.");
console.log("dirPath: " + dirPath);
console.log("tiddlywiki.files location: " + filepath);
}
}
});
return tiddlers;
};
/*
Load the tiddlers from a plugin folder, and package them up into a proper JSON plugin tiddler
*/
$tw.loadPluginFolder = function(filepath,excludeRegExp) {
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
var infoPath = filepath + path.sep + "plugin.info";
if(fs.existsSync(filepath) && fs.statSync(filepath).isDirectory()) {
// Read the plugin information
if(!fs.existsSync(infoPath) || !fs.statSync(infoPath).isFile()) {
console.log("Warning: missing plugin.info file in " + filepath);
return null;
}
2022-04-14 23:41:27 +00:00
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"));
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
pluginInfo.tiddlers = pluginInfo.tiddlers || Object.create(null);
for(var f=0; f<pluginFiles.length; f++) {
var tiddlers = pluginFiles[f].tiddlers;
for(var t=0; t<tiddlers.length; t++) {
var tiddler= tiddlers[t];
if(tiddler.title) {
pluginInfo.tiddlers[tiddler.title] = tiddler;
}
}
}
// Give the plugin the same version number as the core if it doesn't have one
if(!("version" in pluginInfo)) {
pluginInfo.version = $tw.packageInfo.version;
}
// Use "plugin" as the plugin-type if we don't have one
if(!("plugin-type" in pluginInfo)) {
pluginInfo["plugin-type"] = "plugin";
}
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
2022-04-14 23:41:27 +00:00
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {
if($tw.utils.isArray(pluginInfo[field])) {
pluginInfo[field] = $tw.utils.stringifyList(pluginInfo[field]);
}
}
return pluginInfo;
} else {
return null;
}
};
/*
name: Name of the plugin to find
paths: array of file paths to search for it
Returns the path of the plugin folder
*/
$tw.findLibraryItem = function(name,paths) {
var pathIndex = 0;
do {
var pluginPath = path.resolve(paths[pathIndex],"./" + name)
if(fs.existsSync(pluginPath) && fs.statSync(pluginPath).isDirectory()) {
return pluginPath;
}
} while(++pathIndex < paths.length);
return null;
};
/*
name: Name of the plugin to load
paths: array of file paths to search for it
*/
$tw.loadPlugin = function(name,paths) {
var pluginPath = $tw.findLibraryItem(name,paths);
if(pluginPath) {
var pluginFields = $tw.loadPluginFolder(pluginPath);
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
return;
}
}
console.log("Warning: Cannot find plugin '" + name + "'");
};
/*
libraryPath: Path of library folder for these plugins (relative to core path)
envVar: Environment variable name for these plugins
Returns an array of search paths
*/
$tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
var pluginPaths = [path.resolve($tw.boot.corePath,libraryPath)],
env = process.env[envVar];
if(env) {
env.split(path.delimiter).map(function(item) {
if(item) {
pluginPaths.push(item);
}
});
}
return pluginPaths;
};
/*
plugins: Array of names of plugins (eg, "tiddlywiki/filesystemadaptor")
libraryPath: Path of library folder for these plugins (relative to core path)
envVar: Environment variable name for these plugins
*/
$tw.loadPlugins = function(plugins,libraryPath,envVar) {
if(plugins) {
var pluginPaths = $tw.getLibraryItemSearchPaths(libraryPath,envVar);
for(var t=0; t<plugins.length; t++) {
$tw.loadPlugin(plugins[t],pluginPaths);
}
}
};
/*
path: path of wiki directory
options:
parentPaths: array of parent paths that we mustn't recurse into
readOnly: true if the tiddler file paths should not be retained
*/
$tw.loadWikiTiddlers = function(wikiPath,options) {
options = options || {};
var parentPaths = options.parentPaths || [],
wikiInfoPath = path.resolve(wikiPath,$tw.config.wikiInfo),
wikiInfo,
pluginFields;
// Bail if we don't have a wiki info file
if(fs.existsSync(wikiInfoPath)) {
2022-04-14 23:41:27 +00:00
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"));
} else {
return null;
}
2022-04-14 23:41:27 +00:00
// Save the path to the tiddlers folder for the filesystemadaptor
var config = wikiInfo.config || {};
if($tw.boot.wikiPath == wikiPath) {
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
}
// Load any parent wikis
if(wikiInfo.includeWikis) {
parentPaths = parentPaths.slice(0);
parentPaths.push(wikiPath);
$tw.utils.each(wikiInfo.includeWikis,function(info) {
if(typeof info === "string") {
info = {path: info};
}
var resolvedIncludedWikiPath = path.resolve(wikiPath,info.path);
if(parentPaths.indexOf(resolvedIncludedWikiPath) === -1) {
var subWikiInfo = $tw.loadWikiTiddlers(resolvedIncludedWikiPath,{
parentPaths: parentPaths,
readOnly: info["read-only"]
});
// Merge the build targets
wikiInfo.build = $tw.utils.extend([],subWikiInfo.build,wikiInfo.build);
} else {
$tw.utils.error("Cannot recursively include wiki " + resolvedIncludedWikiPath);
}
});
}
// Load any plugins, themes and languages listed in the wiki info file
$tw.loadPlugins(wikiInfo.plugins,$tw.config.pluginsPath,$tw.config.pluginsEnvVar);
$tw.loadPlugins(wikiInfo.themes,$tw.config.themesPath,$tw.config.themesEnvVar);
$tw.loadPlugins(wikiInfo.languages,$tw.config.languagesPath,$tw.config.languagesEnvVar);
// Load the wiki files, registering them as writable
var resolvedWikiPath = path.resolve(wikiPath,$tw.config.wikiTiddlersSubDir);
$tw.utils.each($tw.loadTiddlersFromPath(resolvedWikiPath),function(tiddlerFile) {
if(!options.readOnly && tiddlerFile.filepath) {
$tw.utils.each(tiddlerFile.tiddlers,function(tiddler) {
$tw.boot.files[tiddler.title] = {
filepath: tiddlerFile.filepath,
type: tiddlerFile.type,
2022-04-14 23:41:27 +00:00
hasMetaFile: tiddlerFile.hasMetaFile,
isEditableFile: config["retain-original-tiddler-path"] || tiddlerFile.isEditableFile || tiddlerFile.filepath.indexOf($tw.boot.wikiTiddlersPath) !== 0
};
});
}
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
});
2022-04-14 23:41:27 +00:00
if ($tw.boot.wikiPath == wikiPath) {
// Save the original tiddler file locations if requested
var output = {}, relativePath, fileInfo;
for(var title in $tw.boot.files) {
2022-04-14 23:41:27 +00:00
fileInfo = $tw.boot.files[title];
if(fileInfo.isEditableFile) {
relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath);
fileInfo.originalpath = relativePath;
output[title] =
path.sep === "/" ?
relativePath :
relativePath.split(path.sep).join("/");
}
}
if(Object.keys(output).length > 0){
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
}
}
// Load any plugins within the wiki folder
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
if(fs.existsSync(wikiPluginsPath)) {
var pluginFolders = fs.readdirSync(wikiPluginsPath);
for(var t=0; t<pluginFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiPluginsPath,"./" + pluginFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
// Load any themes within the wiki folder
var wikiThemesPath = path.resolve(wikiPath,$tw.config.wikiThemesSubDir);
if(fs.existsSync(wikiThemesPath)) {
var themeFolders = fs.readdirSync(wikiThemesPath);
for(var t=0; t<themeFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiThemesPath,"./" + themeFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
// Load any languages within the wiki folder
var wikiLanguagesPath = path.resolve(wikiPath,$tw.config.wikiLanguagesSubDir);
if(fs.existsSync(wikiLanguagesPath)) {
var languageFolders = fs.readdirSync(wikiLanguagesPath);
for(var t=0; t<languageFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiLanguagesPath,"./" + languageFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
return wikiInfo;
};
$tw.loadTiddlersNode = function() {
// Load the boot tiddlers
$tw.utils.each($tw.loadTiddlersFromPath($tw.boot.bootPath),function(tiddlerFile) {
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
});
// Load the core tiddlers
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
// Load any extra plugins
$tw.utils.each($tw.boot.extraPlugins,function(name) {
if(name.charAt(0) === "+") { // Relative path to plugin
2022-04-14 23:41:27 +00:00
var pluginFields = $tw.loadPluginFolder(name.substring(1));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
} else {
var parts = name.split("/"),
type = parts[0];
if(parts.length === 3 && ["plugins","themes","languages"].indexOf(type) !== -1) {
$tw.loadPlugins([parts[1] + "/" + parts[2]],$tw.config[type + "Path"],$tw.config[type + "EnvVar"]);
2022-04-14 23:41:27 +00:00
}
}
});
// Load the tiddlers from the wiki directory
if($tw.boot.wikiPath) {
$tw.boot.wikiInfo = $tw.loadWikiTiddlers($tw.boot.wikiPath);
}
};
// End of if($tw.node)
}
/////////////////////////// Main startup function called once tiddlers have been decrypted
/*
Startup TiddlyWiki
*/
2022-04-14 23:41:27 +00:00
$tw.boot.initStartup = function(options) {
// Get the URL hash and check for safe mode
$tw.locationHash = "#";
if($tw.browser && !$tw.node) {
if(location.hash === "#:safe") {
$tw.safeMode = true;
} else {
$tw.locationHash = $tw.utils.getLocationHash();
}
}
// Initialise some more $tw properties
$tw.utils.deepDefaults($tw,{
modules: { // Information about each module
titles: Object.create(null), // hashmap by module title of {fn:, exports:, moduleType:}
types: {} // hashmap by module type of hashmap of exports
},
config: { // Configuration overridables
pluginsPath: "../plugins/",
themesPath: "../themes/",
languagesPath: "../languages/",
editionsPath: "../editions/",
wikiInfo: "./tiddlywiki.info",
wikiPluginsSubDir: "./plugins",
wikiThemesSubDir: "./themes",
wikiLanguagesSubDir: "./languages",
wikiTiddlersSubDir: "./tiddlers",
wikiOutputSubDir: "./output",
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
fileExtensionInfo: Object.create(null), // Map file extension to {type:}
contentTypeInfo: Object.create(null), // Map type to {encoding:,extension:}
pluginsEnvVar: "TIDDLYWIKI_PLUGIN_PATH",
themesEnvVar: "TIDDLYWIKI_THEME_PATH",
languagesEnvVar: "TIDDLYWIKI_LANGUAGE_PATH",
editionsEnvVar: "TIDDLYWIKI_EDITION_PATH"
},
log: {}, // Log flags
unloadTasks: []
});
if(!$tw.boot.tasks.readBrowserTiddlers) {
// For writable tiddler files, a hashmap of title to {filepath:,type:,hasMetaFile:}
$tw.boot.files = Object.create(null);
// System paths and filenames
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
// If there's no arguments then default to `--help`
if($tw.boot.argv.length === 0) {
$tw.boot.argv = ["--help"];
}
// Parse any extra plugin references
$tw.boot.extraPlugins = $tw.boot.extraPlugins || [];
while($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("+") === 0) {
$tw.boot.extraPlugins.push($tw.boot.argv[0].substring(1));
$tw.boot.argv.splice(0,1);
}
// If the first command line argument doesn't start with `--` then we
// interpret it as the path to the wiki folder, which will otherwise default
// to the current folder
if($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("--") !== 0) {
$tw.boot.wikiPath = $tw.boot.argv[0];
$tw.boot.argv = $tw.boot.argv.slice(1);
} else {
$tw.boot.wikiPath = process.cwd();
}
// Read package info
$tw.packageInfo = $tw.packageInfo || require("../package.json");
// Check node version number
if(!$tw.utils.checkVersions(process.version.substr(1),$tw.packageInfo.engines.node.substr(2))) {
$tw.utils.error("TiddlyWiki5 requires node.js version " + $tw.packageInfo.engines.node);
}
}
// Add file extension information
$tw.utils.registerFileType("text/vnd.tiddlywiki","utf8",".tid");
$tw.utils.registerFileType("application/x-tiddler","utf8",".tid");
$tw.utils.registerFileType("application/x-tiddlers","utf8",".multids");
$tw.utils.registerFileType("application/x-tiddler-html-div","utf8",".tiddler");
$tw.utils.registerFileType("text/vnd.tiddlywiki2-recipe","utf8",".recipe");
$tw.utils.registerFileType("text/plain","utf8",".txt");
$tw.utils.registerFileType("text/css","utf8",".css");
$tw.utils.registerFileType("text/html","utf8",[".html",".htm"]);
$tw.utils.registerFileType("application/hta","utf16le",".hta",{deserializerType:"text/html"});
$tw.utils.registerFileType("application/javascript","utf8",".js");
$tw.utils.registerFileType("application/json","utf8",".json");
$tw.utils.registerFileType("application/pdf","base64",".pdf",{flags:["image"]});
$tw.utils.registerFileType("application/zip","base64",".zip");
2022-04-14 23:41:27 +00:00
$tw.utils.registerFileType("application/x-zip-compressed","base64",".zip");
$tw.utils.registerFileType("image/jpeg","base64",[".jpg",".jpeg"],{flags:["image"]});
2022-04-14 23:41:27 +00:00
$tw.utils.registerFileType("image/jpg","base64",[".jpg",".jpeg"],{flags:["image"]});
$tw.utils.registerFileType("image/png","base64",".png",{flags:["image"]});
$tw.utils.registerFileType("image/gif","base64",".gif",{flags:["image"]});
$tw.utils.registerFileType("image/webp","base64",".webp",{flags:["image"]});
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
2022-04-14 23:41:27 +00:00
$tw.utils.registerFileType("image/vnd.microsoft.icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("application/font-woff","base64",".woff");
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
2022-04-14 23:41:27 +00:00
$tw.utils.registerFileType("application/font-woff2","base64",".woff2");
$tw.utils.registerFileType("audio/ogg","base64",".ogg");
2022-04-14 23:41:27 +00:00
$tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]);
$tw.utils.registerFileType("video/webm","base64",".webm");
$tw.utils.registerFileType("video/mp4","base64",".mp4");
$tw.utils.registerFileType("audio/mp3","base64",".mp3");
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.wordprocessingml.document","base64",".docx");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.presentationml.presentation","base64",".pptx");
$tw.utils.registerFileType("text/x-bibtex","utf8",".bib",{deserializerType:"application/x-bibtex"});
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
$tw.utils.registerFileType("application/octet-stream","base64",".octet-stream");
// Create the wiki store for the app
$tw.wiki = new $tw.Wiki();
// Install built in tiddler fields modules
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
// Install the tiddler deserializer modules
$tw.Wiki.tiddlerDeserializerModules = Object.create(null);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
// Call unload handlers in the browser
if($tw.browser) {
window.onbeforeunload = function(event) {
event = event || {};
var result;
$tw.utils.each($tw.unloadTasks,function(task) {
var r = task(event);
if(r) {
result = r;
}
});
return result;
}
}
2022-04-14 23:41:27 +00:00
};
$tw.boot.loadStartup = function(options){
// Load tiddlers
if($tw.boot.tasks.readBrowserTiddlers) {
$tw.loadTiddlersBrowser();
} else {
$tw.loadTiddlersNode();
}
// Load any preloaded tiddlers
if($tw.preloadTiddlers) {
$tw.wiki.addTiddlers($tw.preloadTiddlers);
}
// Give hooks a chance to modify the store
$tw.hooks.invokeHook("th-boot-tiddlers-loaded");
2022-04-14 23:41:27 +00:00
}
$tw.boot.execStartup = function(options){
// Unpack plugin tiddlers
$tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin",$tw.safeMode ? ["$:/core"] : undefined);
$tw.wiki.unpackPluginTiddlers();
// Process "safe mode"
if($tw.safeMode) {
$tw.wiki.processSafeMode();
}
// Register typed modules from the tiddlers we've just loaded
$tw.wiki.defineTiddlerModules();
// And any modules within plugins
$tw.wiki.defineShadowModules();
// Make sure the crypto state tiddler is up to date
if($tw.crypto) {
$tw.crypto.updateCryptoStateTiddler();
}
// Gather up any startup modules
$tw.boot.remainingStartupModules = []; // Array of startup modules
$tw.modules.forEachModuleOfType("startup",function(title,module) {
if(module.startup) {
$tw.boot.remainingStartupModules.push(module);
}
});
// Keep track of the startup tasks that have been executed
$tw.boot.executedStartupModules = Object.create(null);
$tw.boot.disabledStartupModules = $tw.boot.disabledStartupModules || [];
// Repeatedly execute the next eligible task
$tw.boot.executeNextStartupTask(options.callback);
2022-04-14 23:41:27 +00:00
}
/*
Startup TiddlyWiki
*/
$tw.boot.startup = function(options) {
options = options || {};
// Get the URL hash and check for safe mode
$tw.boot.initStartup(options);
$tw.boot.loadStartup(options);
$tw.boot.execStartup(options);
};
/*
Add another unload task
*/
$tw.addUnloadTask = function(task) {
if($tw.unloadTasks.indexOf(task) === -1) {
$tw.unloadTasks.push(task);
}
}
/*
Execute the remaining eligible startup tasks
*/
$tw.boot.executeNextStartupTask = function(callback) {
// Find the next eligible task
var taskIndex = 0, task,
asyncTaskCallback = function() {
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask(callback);
};
while(taskIndex < $tw.boot.remainingStartupModules.length) {
task = $tw.boot.remainingStartupModules[taskIndex];
if($tw.boot.isStartupTaskEligible(task)) {
// Remove this task from the list
$tw.boot.remainingStartupModules.splice(taskIndex,1);
// Assemble log message
var s = ["Startup task:",task.name];
if(task.platforms) {
s.push("platforms:",task.platforms.join(","));
}
if(task.after) {
s.push("after:",task.after.join(","));
}
if(task.before) {
s.push("before:",task.before.join(","));
}
$tw.boot.log(s.join(" "));
// Execute task
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
task.startup();
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask(callback);
} else {
task.startup(asyncTaskCallback);
return true;
}
}
taskIndex++;
}
if(typeof callback === 'function') {
callback();
}
return false;
};
/*
2022-04-14 23:41:27 +00:00
Returns true if we are running on one of the platforms specified in taskModule's
`platforms` array; or if `platforms` property is not defined.
*/
$tw.boot.doesTaskMatchPlatform = function(taskModule) {
var platforms = taskModule.platforms;
if(platforms) {
for(var t=0; t<platforms.length; t++) {
2022-04-14 23:41:27 +00:00
switch (platforms[t]) {
case "browser":
if ($tw.browser) {
return true;
}
break;
case "node":
if ($tw.node) {
return true;
}
break;
default:
$tw.utils.error("Module " + taskModule.name + ": '" + platforms[t] + "' in export.platforms invalid");
}
}
2022-04-14 23:41:27 +00:00
return false;
}
return true;
};
$tw.boot.isStartupTaskEligible = function(taskModule) {
var t;
// Check that the platform is correct
if(!$tw.boot.doesTaskMatchPlatform(taskModule)) {
return false;
}
var name = taskModule.name,
remaining = $tw.boot.remainingStartupModules;
if(name) {
// Fail if this module is disabled
if($tw.boot.disabledStartupModules.indexOf(name) !== -1) {
return false;
}
// Check that no other outstanding tasks must be executed before this one
for(t=0; t<remaining.length; t++) {
var task = remaining[t];
if(task.before && task.before.indexOf(name) !== -1) {
if($tw.boot.doesTaskMatchPlatform(task) || (task.name && $tw.boot.disabledStartupModules.indexOf(name) !== -1)) {
return false;
}
}
}
}
// Check that all of the tasks that we must be performed after has been done
var after = taskModule.after;
if(after) {
for(t=0; t<after.length; t++) {
if(!$tw.boot.executedStartupModules[after[t]]) {
return false;
}
}
}
return true;
};
/*
Global Hooks mechanism which allows plugins to modify default functionality
*/
$tw.hooks = $tw.hooks || { names: {}};
/*
Add hooks to the hashmap
*/
$tw.hooks.addHook = function(hookName,definition) {
if($tw.utils.hop($tw.hooks.names,hookName)) {
$tw.hooks.names[hookName].push(definition);
}
else {
$tw.hooks.names[hookName] = [definition];
}
};
/*
Invoke the hook by key
*/
$tw.hooks.invokeHook = function(hookName /*, value,... */) {
var args = Array.prototype.slice.call(arguments,1);
if($tw.utils.hop($tw.hooks.names,hookName)) {
for (var i = 0; i < $tw.hooks.names[hookName].length; i++) {
args[0] = $tw.hooks.names[hookName][i].apply(null,args);
}
}
return args[0];
};
/////////////////////////// Main boot function to decrypt tiddlers and then startup
$tw.boot.boot = function(callback) {
// Initialise crypto object
$tw.crypto = new $tw.utils.Crypto();
// Initialise password prompter
if($tw.browser && !$tw.node) {
$tw.passwordPrompt = new $tw.utils.PasswordPrompt();
}
// Preload any encrypted tiddlers
$tw.boot.decryptEncryptedTiddlers(function() {
// Startup
$tw.boot.startup({callback: callback});
});
};
/////////////////////////// Autoboot in the browser
if($tw.browser && !$tw.boot.suppressBoot) {
$tw.boot.boot();
}
return $tw;
});
if(typeof(exports) !== "undefined") {
exports.TiddlyWiki = _boot;
} else {
_boot(window.$tw);
}
2022-04-14 23:41:27 +00:00
//# sourceURL=$:/boot/boot.js
</script>
</div>
<!--~~ Raw markup for the bottom of the body section ~~-->
</body>
</html>